February 28, 2006 at 11:13 am
Hi
I have a value which I retrieve in a SQL query which is a Booking Date for system.
In a later inner join I need to get more information about this booking as follows:
LEFT JOIN
(
SELECT
B.homeworkerid,
SUM(transactionamount) AS TransactionAmount
FROM
tbl_hp_bookings_transactions BT WITH (NOLOCK),
tbl_hp_bookings B WITH (NOLOCK)
WHERE
BT.bookingid = B.bookingid
AND
BT.TransactionDate BETWEEN ******DATE RANGE******
GROUP BY B.homeworkerid
) dtHWDiscount
ON
(dtHWDiscount.homeworkerid = AU.userid)
Previously my queries have only needed the date range as sent in by the query so I have used something like:
@StartSerial AND DateAdd(d,1,@EndSerial)
However for this particular query I need to take the date in the main query (which is held as B.BookingDate) and then retrive all information that was recorded in this month.
For example if B.BookingDate is 28/12/2005 then I need the date range in the inner join to become:
01/12/2005 AND 01/01/2006
How do I create a date range from the value I retrieve from the other table?
Thanks in advance for any assistance...
February 28, 2006 at 11:29 am
Try this:
LEFT JOIN
(
SELECT
B.homeworkerid,
SUM(transactionamount) AS TransactionAmount
FROM
tbl_hp_bookings_transactions BT WITH (NOLOCK),
tbl_hp_bookings B WITH (NOLOCK)
WHERE
BT.bookingid = B.bookingid
AND
datepart(m, BT.TransactionDate) = datepart(m, @StartSerial)
GROUP BY B.homeworkerid
) dtHWDiscount
ON
(dtHWDiscount.homeworkerid = AU.userid)
or this:
declare @serialstart datetime
select @serialstart = '20 Dec 2006'
declare @startdate datetime
declare @Enddate datetime
select @StartDate = convert(datetime, convert(varchar, datepart(m, @SerialStart)) + '/01/' + convert(varchar, datepart(yyyy, @SerialStart))),
@Enddate = convert(datetime, convert(varchar, datepart(m, dateadd(m, 1, @SerialStart))) + '/01/' + convert(varchar, datepart(yyyy, dateadd(m, 1, @SerialStart))))
select @StartDate, @Enddate
LEFT JOIN
(
SELECT
B.homeworkerid,
SUM(transactionamount) AS TransactionAmount
FROM
tbl_hp_bookings_transactions BT WITH (NOLOCK),
tbl_hp_bookings B WITH (NOLOCK)
WHERE
BT.bookingid = B.bookingid
AND
BT.TransactionDate between @startdate and @Enddate
GROUP BY B.homeworkerid
) dtHWDiscount
ON
(dtHWDiscount.homeworkerid = AU.userid)
February 28, 2006 at 11:38 am
Hi
I went for this first one:
LEFT JOIN
(
SELECT
B.homeworkerid,
SUM(transactionamount) AS TransactionAmount
FROM
tbl_hp_bookings_transactions BT WITH (NOLOCK),
tbl_hp_bookings B WITH (NOLOCK)
WHERE
BT.bookingid = B.bookingid
AND
datepart(m, BT.TransactionDate) = datepart(m, B.BookingDate)
GROUP BY B.homeworkerid
) dtHWDiscount
ON
(dtHWDiscount.homeworkerid = AU.userid)
but subbed in B.BookingDate in place of @StartSerial as I needed to use the retrieved B.BookingDate value as it could be a different month to @StartSerial which is basically just the date range for the report.
Assuming that's OK I seem to get the results I was expecting. Does that all sound right? If so, thanks very much!
February 28, 2006 at 11:44 am
Just 2 general comments:
Best practice dictates that table names should be singular not plural because on row is a booking, not a bookings.
use INNER JOIN syntax such as:
FROM tbl_hp_bookings_transactions BT WITH (NOLOCK)
INNER JOIN tbl_hp_bookings B WITH (NOLOCK)
ON BT.bookingid = B.bookingid and datepart(m, BT.TransactionDate) = datepart(m, B.BookingDate)
March 1, 2006 at 4:00 pm
Ok - end of month suggests I didn't quite get this right. The snippet below is a JOIN from my main query and I am having a problem feeding the correct date range in to the join.
The date range is different for each record that is retrieved in the main SELECT query. The value that holds the date in the main select query is B.BookingID (but it's a different B table to that listed below).
How can I get a date for each record I retrieve and then act on this in the JOIN? I tried @OrigBookingDate = B.BookingID but I get an error about not being able to assign variables at the same time as retrieving data.
Any help is much appreciated as I am tearing my hair out now!
Thanks
LEFT JOIN
(
SELECT
B.homeworkerid,
SUM(transactionamount) AS TransactionAmount
FROM
tbl_hp_bookings_transactions BT WITH (NOLOCK),
tbl_hp_bookings B WITH (NOLOCK),
tbl_hp_customers C WITH (NOLOCK)
WHERE
BT.bookingid = B.bookingid
AND
B.CustomerID = C.CustomerID
AND
B.ConfirmTag = 'Y'
AND
C.OwnContact != 'Y'
AND
BT.TransactionDate BETWEEN startdate AND enddate
AND
BT.transactiontypeid = 1000
GROUP BY
B.homeworkerid
) dtHWRevenue
ON
(dtHWRevenue.homeworkerid = AU.userid)
March 1, 2006 at 4:04 pm
For reference the whole procedure is shown below - I am sure it is not very well optimised but as mentioned in previous posts I am filling in and somewhat out of my depth! It's the HWRevenue JOIN which is incorrect as it is taking the input date range @StartSerial but should be taking the B.BookingDate value in the main query:
CREATE PROCEDURE sproc_HP_CMC_Reports_Commission_AdminByHW
(
@Field varchar(50),
@SortDir varchar(5),
@StartSerial varchar(10),
@EndSerial varchar(10),
@HomeworkerID int
)
AS
SELECT
B.BookingID,
ISNULL(UPPER(C.CustomerSurname),'') AS CustomerSurname,
ISNULL(UPPER(C.CustomerFirstname),'') AS CustomerFirstname,
B.CustomerID,
B.YTReference,
B.DepartureDate,
B.TransactionCost,
UPPER(AU.Firstname),
UPPER(AU.Surname),
ISNULL(dtMonthlyRevenue.TransactionAmount,0),
ISNULL(dtMonthlyRevenue.CommissionAmount,0),
ISNULL(dtMonthlyDiscounts.MonthlyDiscount,0),
ISNULL(dtMonthlyDiscounts.CommissionDeductions,0),
ISNULL(dtCardFees.CardFeeTotal,0),
(ISNULL(dtMonthlyRevenue.CommissionAmount,0)-ISNULL(dtMonthlyDiscounts.CommissionDeductions,0)+ISNULL(dtCardFees.CardFeeTotal,0)-B.TransactionCost) AS NetCommission,
ISNULL(dtHWRevenue.transactionamount,0),
ISNULL(dtHWDiscount.transactionamount,0),
ISNULL(dtHWRevenue.transactionamount,0)-ISNULL(dtHWDiscount.transactionamount,0) AS HWBookings,
C.OwnContact,
(CASE
WHEN C.OwnContact = 'Y' THEN 50
WHEN C.OwnContact = 'N' AND (ISNULL(dtHWRevenue.transactionamount,0)-ISNULL(dtHWDiscount.transactionamount,0)) >= 40000 THEN 35
WHEN C.OwnContact = 'N' AND (ISNULL(dtHWRevenue.transactionamount,0)-ISNULL(dtHWDiscount.transactionamount,0)) >= 30000 THEN 30
ELSE 25
END) AS Rate,
((CAST((CASE
WHEN C.OwnContact = 'Y' THEN 50
WHEN C.OwnContact = 'N' AND (ISNULL(dtHWRevenue.transactionamount,0)-ISNULL(dtHWDiscount.transactionamount,0)) >= 40000 THEN 35
WHEN C.OwnContact = 'N' AND (ISNULL(dtHWRevenue.transactionamount,0)-ISNULL(dtHWDiscount.transactionamount,0)) >= 30000 THEN 30
ELSE 25
END) AS DECIMAL(18,2))/100)* (ISNULL(dtMonthlyRevenue.CommissionAmount,0)-ISNULL(dtMonthlyDiscounts.CommissionDeductions,0)+ISNULL(dtCardFees.CardFeeTotal,0)-B.TransactionCost)
) AS HWComm,
B.BookingDate
--
FROM
tbl_hp_bookings B WITH (NOLOCK)
--get booking transactions
INNER JOIN
tbl_hp_bookings_transactions BT WITH (NOLOCK)
ON
B.BookingID = BT.BookingID
AND
BT.TransactionTypeID 1001
--get customer surname
LEFT JOIN
tbl_hp_customers C WITH (NOLOCK)
ON
B.CustomerID = C.CustomerID
--get homeworker name
LEFT JOIN
tbl_hp_adminusers AU WITH (NOLOCK)
ON
B.HomeworkerID = AU.UserID
--get booking totals
LEFT JOIN
(
SELECT
B.bookingid,
SUM(transactionamount) AS TransactionAmount,
SUM(commissionamount) AS CommissionAmount
FROM
tbl_hp_bookings_transactions BT WITH (NOLOCK),
tbl_hp_bookings B WITH (NOLOCK)
WHERE
BT.bookingid = B.bookingid
AND
B.ConfirmTag = 'Y'
AND
B.PaidTag = 'Y'
AND
BT.transactiontypeid = 1000
GROUP BY
B.bookingid
) dtMonthlyRevenue
ON
(dtMonthlyRevenue.bookingid = B.bookingid)
-- get commissions & discounts
LEFT JOIN
(
SELECT
B.bookingid,
SUM(transactionamount) AS MonthlyDiscount,
SUM(commissionamount) AS CommissionDeductions
FROM
tbl_hp_bookings_transactions BT WITH (NOLOCK),
tbl_hp_bookings B WITH (NOLOCK)
WHERE
BT.bookingid = B.bookingid
AND
B.ConfirmTag = 'Y'
AND
B.PaidTag = 'Y'
AND
BT.transactiontypeid = 1002
GROUP BY
B.bookingid
) dtMonthlyDiscounts
ON
(dtMonthlyDiscounts.bookingid = B.bookingid)
-- get commissions & discounts
LEFT JOIN
(
SELECT
B.bookingid,
SUM(transactionamount) AS CardFeeTotal
FROM
tbl_hp_bookings_transactions BT WITH (NOLOCK),
tbl_hp_bookings B WITH (NOLOCK)
WHERE
BT.bookingid = B.bookingid
AND
B.ConfirmTag = 'Y'
AND
B.PaidTag = 'Y'
AND
BT.transactiontypeid = 1003
GROUP BY
B.bookingid
) dtCardFees
ON
(dtCardFees.bookingid = B.bookingid)
--get booking totals per homeworker
LEFT JOIN
(
SELECT
B.homeworkerid,
SUM(transactionamount) AS TransactionAmount
FROM
tbl_hp_bookings_transactions BT WITH (NOLOCK),
tbl_hp_bookings B WITH (NOLOCK),
tbl_hp_customers C WITH (NOLOCK)
WHERE
BT.bookingid = B.bookingid
AND
B.CustomerID = C.CustomerID
AND
B.ConfirmTag = 'Y'
AND
C.OwnContact != 'Y'
AND
BT.TransactionDate BETWEEN @StartSerial AND DateAdd(d,1,@EndSerial)
AND
BT.transactiontypeid = 1000
GROUP BY
B.homeworkerid
) dtHWRevenue
ON
(dtHWRevenue.homeworkerid = AU.userid)
LEFT JOIN
(
SELECT
B.homeworkerid,
SUM(transactionamount) AS TransactionAmount
FROM
tbl_hp_bookings_transactions BT WITH (NOLOCK),
tbl_hp_bookings B WITH (NOLOCK),
tbl_hp_customers C WITH (NOLOCK)
WHERE
B.CustomerID = C.CustomerID
AND
BT.bookingid = B.bookingid
AND
B.ConfirmTag = 'Y'
AND
C.OwnContact != 'Y'
AND
BT.TransactionDate BETWEEN @StartSerial AND DateAdd(d,1,@EndSerial)
AND
BT.transactiontypeid = 1002
GROUP BY
B.homeworkerid
) dtHWDiscount
ON
(dtHWDiscount.homeworkerid = AU.userid)
--where & group by clauses
WHERE
B.PaidTag = 'Y'
AND
B.PaidDate BETWEEN @StartSerial AND DateAdd(d,1,@EndSerial)
AND
B.HomeworkerID = @HomeworkerID
GROUP BY
B.BookingID,
B.YTReference,
B.CustomerID,
B.DepartureDate,
B.TransactionCost,
AU.FirstName,
AU.Surname,
C.CustomerFirstname,
dtMonthlyRevenue.TransactionAmount,
dtMonthlyRevenue.CommissionAmount,
dtMonthlyDiscounts.MonthlyDiscount,
dtMonthlyDiscounts.CommissionDeductions,
dtCardFees.CardFeeTotal,
dtHWRevenue.TransactionAmount,
dtHWDiscount.TransactionAmount,
C.OwnContact,
B.BookingDate,
C.CustomerSurname /*distinct bookings*/
ORDER BY
CASE
WHEN @SortDir = 'a' AND @Field = 'client' THEN C.CustomerSurname
WHEN @SortDir = 'a' AND @Field = 'expert' THEN AU.Firstname
END ASC,
CASE
WHEN @SortDir = 'd' AND @Field = 'client' THEN C.CustomerSurname
WHEN @SortDir = 'd' AND @Field = 'expert' THEN AU.Firstname
END DESC,
--numeric sorts
CASE
WHEN @SortDir = 'a' AND @Field = 'ref' THEN B.ytreference
END ASC,
CASE
WHEN @SortDir = 'd' AND @Field = 'ref' THEN B.ytreference
END DESC,
--currency sorts
CASE
WHEN @SortDir = 'a' AND @Field = 'transchg' THEN B.TransactionCost
WHEN @SortDir = 'a' AND @Field = 'value' THEN dtMonthlyRevenue.TransactionAmount
WHEN @SortDir = 'a' AND @Field = 'grossc' THEN dtMonthlyRevenue.CommissionAmount
WHEN @SortDir = 'a' AND @Field = 'discount' THEN dtMonthlyDiscounts.CommissionDeductions
WHEN @SortDir = 'a' AND @Field = 'ccfee' THEN dtCardFees.CardFeeTotal
WHEN @SortDir = 'a' AND @Field = 'netc' THEN (ISNULL(dtMonthlyRevenue.CommissionAmount,0)-ISNULL(dtMonthlyDiscounts.CommissionDeductions,0)+ISNULL(dtCardFees.CardFeeTotal,0)-B.TransactionCost)
END ASC,
CASE
WHEN @SortDir = 'd' AND @Field = 'transchg' THEN B.TransactionCost
WHEN @SortDir = 'd' AND @Field = 'value' THEN dtMonthlyRevenue.TransactionAmount
WHEN @SortDir = 'd' AND @Field = 'grossc' THEN dtMonthlyRevenue.CommissionAmount
WHEN @SortDir = 'd' AND @Field = 'discount' THEN dtMonthlyDiscounts.CommissionDeductions
WHEN @SortDir = 'd' AND @Field = 'ccfee' THEN dtCardFees.CardFeeTotal
WHEN @SortDir = 'd' AND @Field = 'netc' THEN (ISNULL(dtMonthlyRevenue.CommissionAmount,0)-ISNULL(dtMonthlyDiscounts.CommissionDeductions,0)+ISNULL(dtCardFees.CardFeeTotal,0)-B.TransactionCost)
END DESC,
--date sorts
CASE
WHEN @SortDir = 'a' AND @Field = 'dod' THEN B.DepartureDate
END ASC,
CASE
WHEN @SortDir = 'd' AND @Field = 'dod' THEN B.DepartureDate
END DESC
GO
March 1, 2006 at 5:43 pm
In terms of patience it was surely good exercise to write this procedure.
When I see 'one-size-fits-all' procedures like this I'd suggest you take a side view on some basic oo-design guidelines. We're talking of SQL, clearly, but can you administer this? Will you really be able to adjust this to changing business rules?
A few simple things:
1. Keep the ordering out of the procedure, for example by first creating the result set within a table valued function or a temptable and later applying the ordering.
2. Don't mix up different style join-syntax.
3. Apply 'reader' information AFTER you've calculated the core facts. (e.g. ISNULL(UPPER(C.CustomerSurname),'') AS CustomerSurname, ISNULL(UPPER(C.CustomerFirstname),'') AS CustomerFirstname etc.... ) AND resolve the Core within a derived table for clarity.
I'd rather not have calculated my revenue with this procedure
How about posting the databse design? It's surely questionable.
_/_/_/ paramind _/_/_/
March 2, 2006 at 12:46 am
Yep it's not the best query in the world for sure. I didn't design the database so it's a case of trying to get the data out of it now if possible.
I have cut the query down below to focus on the part that needs attention.
The date range in the main WHERE clause is passed in to the query by a parameter (shown as 20060201 to 20060228) and so this is not a problem to calculate.
For each booking row that is retrieved by this query it will have a field which holds the original booking date. What I am then trying to do from this is take that booking date and get the value of all bookings that occurred in the month of that booking date. This figure then tells me the performance for the user in that month and from there I can calculate the commission payment due.
I can't figure out how I can use the figure B.BookingDate in the JOIN later in the query (i.e. to create the date range shown below as 20051201 to 20051231). Can anybody offer any suggestions?
SELECT
B.BookingID,
AU.Surname,
B.DepartureDate,
B.BookingDate,
ISNULL(dtHWRevenue.transactionamount,0)
FROM
tbl_hp_bookings B WITH (NOLOCK)
--join to get all matching transactions for retrieved bookings
LEFT JOIN
tbl_hp_bookings_transactions BT WITH (NOLOCK)
ON
B.BookingID = BT.BookingID
--get the id of the adminuser who placed the booking
LEFT JOIN
tbl_hp_adminusers AU WITH (NOLOCK)
ON
B.HomeworkerID = AU.UserID
--get total of all bookings for the month when the individual booking was made - not the same as current report range
LEFT JOIN
(
SELECT
BK.homeworkerid,
SUM(transactionamount) AS TransactionAmount
FROM
tbl_hp_bookings_transactions BKT WITH (NOLOCK),
tbl_hp_bookings BK WITH (NOLOCK)
WHERE
BKT.bookingid = BK.bookingid
AND
BKT.TransactionDate BETWEEN '20051201' AND '20051231'
GROUP BY
BK.homeworkerid
) dtHWRevenue
ON
(dtHWRevenue.homeworkerid = AU.userid)
WHERE
B.PaidDate BETWEEN '20060201' AND '20060228'
GROUP BY
B.BookingID,
AU.Surname,
B.DepartureDate,
B.BookingDate,
dtHWRevenue.TransactionAmount
March 2, 2006 at 4:58 am
-- The basics for your special date range / just to clrify and test
DECLARE @dtmSome DATETIME,
@dtmStart DATETIME,
@dtmEnd DATETIME
SET @dtmSome = '20060223'
SET @dtmStart = CAST(CAST(DATEPART(yyyy,@dtmSome)AS CHAR(4)) + REPLACE(STR(DATEPART(mm,@dtmSome),2),' ','0') + '01' AS DATETIME)
SET @dtmEnd = DATEADD(m,1,@dtmStart)
PRINT @dtmStart
PRINT @dtmEnd
-----------------------------------
-- a few more things:
-- 1. I have removed the NOLOCK hints for clarity only 😉
-- 2. I have changed your join syntax in the inner query (not a must, but good advise)
-- 3. I'd rather not use "between"! Between means, you include the upper end of the interval:
-- if so, you will have to care of the time portion: don't fumble around with milliseconds like lots of people do
-- not concise, not elegant, potentially wrong
-- 4. of course should pass parameters for the dates in the where clause
-- 5. and last: It will slow down performance a bit, but I'd prefer to have the calculation in question
-- in a user defined function with the parameters udf_Calc_dtHWRevenue(@dtminQuestion, @HomeWorkerID)
SELECT
B.BookingID,
AU.Surname,
B.DepartureDate,
B.BookingDate,
ISNULL(dtHWRevenue.transactionamount,0)
FROM tbl_hp_bookings B
LEFT JOIN tbl_hp_bookings_transactions BT
ON B.BookingID = BT.BookingID
LEFT JOIN tbl_hp_adminusers AU
ON B.HomeworkerID = AU.UserID
LEFT JOIN
(SELECT
BK.homeworkerid,
SUM(transactionamount) AS TransactionAmount
FROM tbl_hp_bookings_transactions BKT
INNER JOIN tbl_hp_bookings BK
ON BKT.bookingid = BK.bookingid
WHERE
BKT.TransactionDate >= CAST(CAST(DATEPART(yyyy,B.BookingDate)AS CHAR(4)) + REPLACE(STR(DATEPART(mm,B.BookingDate),2),' ','0') + '01' AS DATETIME)
AND BKT.TransactionDate < DATEADD(m,1,CAST(CAST(DATEPART(yyyy,B.BookingDate)AS CHAR(4)) + REPLACE(STR(DATEPART(mm,B.BookingDate),2),' ','0') + '01' AS DATETIME))
GROUP BY
BK.homeworkerid) dtHWRevenue
ON dtHWRevenue.homeworkerid = AU.userid
WHERE
B.PaidDate BETWEEN '20060201' AND '20060228'
GROUP BY
B.BookingID,
AU.Surname,
B.DepartureDate,
B.BookingDate,
dtHWRevenue.TransactionAmount
-- I hope this helps
_/_/_/ paramind _/_/_/
March 2, 2006 at 5:17 am
-- A version with a table valued UDF, just to get the idea (NOT TESTED, care of performance)
CREATE FUNCTION udf_Calc_dtHWRevenue
(@dtminQuestion DATETIME)
RETURNS @tblBookingSum TABLE (HomeworkerID INT PRIMARY KEY,
TransactionAmount MONEY DEFAULT 0)
AS
BEGIN
DECLARE @dtmStart DATETIME,
@dtmEnd DATETIME
SET @dtmStart = CAST(CAST(DATEPART(yyyy,@dtminQuestion)AS CHAR(4)) + REPLACE(STR(DATEPART(mm,@dtminQuestion),2),' ','0') + '01' AS DATETIME)
SET @dtmEnd = DATEADD(m,1,@dtmStart)
INSERT INTO @tblBookingSum
SELECT
BK.homeworkerid,
COALESCE(SUM(transactionamount),0) --COALESCE IS THE ANSI-equivalent OF ISNULL( ...
FROM tbl_hp_bookings_transactions BKT
INNER JOIN tbl_hp_bookings BK
ON BKT.bookingid = BK.bookingid
WHERE
BKT.TransactionDate >= @dtmStart
AND BKT.TransactionDate < @dtmEnd
GROUP BY
BK.homeworkerid
RETURN
END
------------------------------------------------------
SELECT
B.BookingID,
AU.Surname,
B.DepartureDate,
B.BookingDate,
ISNULL(dtHWRevenue.transactionamount,0)
FROM tbl_hp_bookings B
LEFT JOIN tbl_hp_bookings_transactions BT
ON B.BookingID = BT.BookingID
LEFT JOIN tbl_hp_adminusers AU
ON B.HomeworkerID = AU.UserID
LEFT JOIN dbo.udf_Calc_dtHWRevenue(B.BookingDate) AS dtHWRevenue
ON AU.UserID = dtHWRevenue.HomeworkerID
WHERE
B.PaidDate BETWEEN '20060201' AND '20060228'
GROUP BY
B.BookingID,
AU.Surname,
B.DepartureDate,
B.BookingDate,
dtHWRevenue.TransactionAmount
_/_/_/ paramind _/_/_/
March 2, 2006 at 5:32 am
-- And an inline version of the above function (shoulf perform better)
CREATE FUNCTION udf_Calc_dtHWRevenue_02
(@dtminQuestion DATETIME)
RETURNS TABLE
AS
RETURN
(SELECT
BK.homeworkerid,
COALESCE(SUM(transactionamount),0) AS TransactionAmount
FROM tbl_hp_bookings_transactions BKT
INNER JOIN tbl_hp_bookings BK
ON BKT.bookingid = BK.bookingid
WHERE
BKT.TransactionDate >= CAST(CAST(DATEPART(yyyy,@dtminQuestion)AS CHAR(4)) + REPLACE(STR(DATEPART(mm,@dtminQuestion),2),' ','0') + '01' AS DATETIME)
AND BKT.TransactionDate < DATEADD(m,1,CAST(CAST(DATEPART(yyyy,@dtminQuestion)AS CHAR(4)) + REPLACE(STR(DATEPART(mm,@dtminQuestion),2),' ','0') + '01' AS DATETIME))
GROUP BY
BK.homeworkerid)
_/_/_/ paramind _/_/_/
March 2, 2006 at 7:26 am
Hello - sorry I completely missed one of the posts in this query. I am looking at the solution now!
Simon
March 2, 2006 at 7:38 am
Hello
I got this response from Query Analyzer:
The column prefix 'B' does not match with a table name or alias name used in the query. The query I tried was:
-- The basics for your special date range / just to clrify and test
DECLARE @dtmSome DATETIME,
@dtmStart DATETIME,
@dtmEnd DATETIME
SET @dtmSome = '20060223'
SET @dtmStart = CAST(CAST(DATEPART(yyyy,@dtmSome)AS CHAR(4)) + REPLACE(STR(DATEPART(mm,@dtmSome),2),' ','0') + '01' AS DATETIME)
SET @dtmEnd = DATEADD(m,1,@dtmStart)
PRINT @dtmStart
PRINT @dtmEnd
-----------------------------------
-- a few more things:
-- 1. I have removed the NOLOCK hints for clarity only 😉
-- 2. I have changed your join syntax in the inner query (not a must, but good advise)
-- 3. I'd rather not use "between"! Between means, you include the upper end of the interval:
-- if so, you will have to care of the time portion: don't fumble around with milliseconds like lots of people do
-- not concise, not elegant, potentially wrong
-- 4. of course should pass parameters for the dates in the where clause
-- 5. and last: It will slow down performance a bit, but I'd prefer to have the calculation in question
-- in a user defined function with the parameters udf_Calc_dtHWRevenue(@dtminQuestion, @HomeWorkerID)
SELECT
B.BookingID,
AU.Surname,
B.DepartureDate,
B.BookingDate,
ISNULL(dtHWRevenue.transactionamount,0)
FROM tbl_hp_bookings B
LEFT JOIN tbl_hp_bookings_transactions BT
ON B.BookingID = BT.BookingID
LEFT JOIN tbl_hp_adminusers AU
ON B.HomeworkerID = AU.UserID
LEFT JOIN
(SELECT
BK.homeworkerid,
SUM(transactionamount) AS TransactionAmount
FROM tbl_hp_bookings_transactions BKT
INNER JOIN tbl_hp_bookings BK
ON BKT.bookingid = BK.bookingid
WHERE
BKT.TransactionDate >= CAST(CAST(DATEPART(yyyy,B.BookingDate)AS CHAR(4)) + REPLACE(STR(DATEPART(mm,B.BookingDate),2),' ','0') + '01' AS DATETIME)
AND BKT.TransactionDate < DATEADD(m,1,CAST(CAST(DATEPART(yyyy,B.BookingDate)AS CHAR(4)) + REPLACE(STR(DATEPART(mm,B.BookingDate),2),' ','0') + '01' AS DATETIME))
GROUP BY
BK.homeworkerid) dtHWRevenue
ON dtHWRevenue.homeworkerid = AU.userid
WHERE
B.PaidDate BETWEEN '20060201' AND '20060228'
GROUP BY
B.BookingID,
AU.Surname,
B.DepartureDate,
B.BookingDate,
dtHWRevenue.TransactionAmount
I really appreciate your assistance...
March 2, 2006 at 7:59 am
Unfortunately, I cannot test without the tables at hand. Can you script them (using QA) ? Now that we've gone that far, we should finish it up
Have you tried the second function? You can test it independantly. This will also be good for control:
CREATE FUNCTION udf_Calc_dtHWRevenue_02
(@dtminQuestion DATETIME)
RETURNS TABLE
AS
RETURN
(SELECT
BK.homeworkerid,
COALESCE(SUM(transactionamount),0) AS TransactionAmount
FROM tbl_hp_bookings_transactions BKT
INNER JOIN tbl_hp_bookings BK
ON BKT.bookingid = BK.bookingid
WHERE
BKT.TransactionDate >= CAST(CAST(DATEPART(yyyy,@dtminQuestion)AS CHAR(4)) + REPLACE(STR(DATEPART(mm,@dtminQuestion),2),' ','0') + '01' AS DATETIME)
AND BKT.TransactionDate < DATEADD(m,1,CAST(CAST(DATEPART(yyyy,@dtminQuestion)AS CHAR(4)) + REPLACE(STR(DATEPART(mm,@dtminQuestion),2),' ','0') + '01' AS DATETIME))
GROUP BY
BK.homeworkerid)
-------------------
SELECT * FROM dbo.udf_Calc_dtHWRevenue_02(@someDate)
... should return the sum for every homeworkerid in the specified month.
_/_/_/ paramind _/_/_/
March 2, 2006 at 8:51 am
Hi
I have scripted the two tables involved (I think!!) - see below.
The 2nd function certainly seems to retrieve broadly what I expect it to. Now just need to wrap it all up in 1 query?!
Simon
CREATE TABLE [tbl_hp_bookings] (
[BookingID] [int] IDENTITY (2000, 1) NOT NULL ,
[CustomerID] [int] NOT NULL ,
[DestinationID] [int] NOT NULL ,
[DestinationText] [varchar] (100) COLLATE Latin1_General_CI_AS NULL ,
[DepartureDate] [datetime] NOT NULL ,
[BookingDate] [datetime] NULL CONSTRAINT [DF_tbl_hp_bookings_BookingDate] DEFAULT (getdate()),
[Duration] [int] NULL ,
[Supplier] [varchar] (255) COLLATE Latin1_General_CI_AS NULL ,
[GiftTag] [varchar] (1) COLLATE Latin1_General_CI_AS NOT NULL CONSTRAINT [DF_tbl_hp_bookings_GiftTag] DEFAULT ('N'),
[Discount] [money] NOT NULL CONSTRAINT [DF_tbl_hp_bookings_Discount] DEFAULT (0),
[TransactionCost] [money] NOT NULL CONSTRAINT [DF_tbl_hp_bookings_TransactionCost] DEFAULT (0.00),
[HPCardFee] [money] NOT NULL CONSTRAINT [DF_tbl_hp_bookings_HPCardFee] DEFAULT (0),
[ConfirmTag] [varchar] (1) COLLATE Latin1_General_CI_AS NOT NULL CONSTRAINT [DF_tbl_hp_bookings_ConfirmTag] DEFAULT ('N'),
[YTReference] [varchar] (50) COLLATE Latin1_General_CI_AS NULL ,
[PaidTag] [varchar] (1) COLLATE Latin1_General_CI_AS NOT NULL CONSTRAINT [DF_tbl_hp_bookings_PaidTag] DEFAULT ('N'),
[CommissionRate] [numeric](18, 0) NOT NULL CONSTRAINT [DF_tbl_hp_bookings_CommissionRate] DEFAULT (25),
[HWContact] [varchar] (1) COLLATE Latin1_General_CI_AS NOT NULL CONSTRAINT [DF_tbl_hp_bookings_HWContact] DEFAULT ('N'),
[PaidDate] [datetime] NULL ,
[HomeworkerID] [int] NOT NULL ,
[QuoteID] [int] NULL CONSTRAINT [DF_tbl_hp_bookings_QuoteID] DEFAULT (0),
[EnquiryID] [int] NULL ,
[HWConfirmTag] [varchar] (1) COLLATE Latin1_General_CI_AS NULL CONSTRAINT [DF_tbl_hp_bookings_HWConfirmTag] DEFAULT ('N'),
[ConfMailSent] [char] (1) COLLATE Latin1_General_CI_AS NULL CONSTRAINT [DF_tbl_hp_bookings_ConfMailSent] DEFAULT ('N'),
CONSTRAINT [PK_tbl_hp_bookings] PRIMARY KEY CLUSTERED
(
[BookingID]
) WITH FILLFACTOR = 90 ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [tbl_hp_bookings_transactions] (
[TransactionID] [int] IDENTITY (1000, 1) NOT NULL ,
[BookingID] [int] NOT NULL ,
[TransactionDesc] [varchar] (255) COLLATE Latin1_General_CI_AS NOT NULL ,
[TransactionAmount] [money] NOT NULL CONSTRAINT [DF_tbl_hp_bookings_transactions_TransactionAmount] DEFAULT (0),
[TransactionDate] [datetime] NOT NULL CONSTRAINT [DF_tbl_hp_bookings_transactions_TransactionDate] DEFAULT (getdate()),
[TransactionTypeID] [int] NOT NULL ,
[HomeworkerID] [int] NOT NULL ,
[CommissionAmount] [money] NOT NULL CONSTRAINT [DF_tbl_hp_bookings_transactions_CommissionAmount] DEFAULT (0),
[SupplierID] [int] NOT NULL CONSTRAINT [DF_tbl_hp_bookings_transactions_SupplierID] DEFAULT (0),
CONSTRAINT [PK_tbl_hp_bookings_transactions] PRIMARY KEY CLUSTERED
(
[TransactionID]
) WITH FILLFACTOR = 90 ON [PRIMARY]
) ON [PRIMARY]
GO
Viewing 15 posts - 1 through 15 (of 20 total)
You must be logged in to reply to this topic. Login to reply