How to remove duplicate SQL rows based off 1 column by comparing 2 different date columns? - sql

I have a query that joins multiple tables/views and displays rows that are identified by a column named VIN. I want to only show the VIN one time based off of the most recent date from 2 different date fields (OPEN DATE & INVOICE DATE) IF both dates have a Value.
If Invoice Date is Null, show the row that has the most recent Open Date for that VIN. For example, if I have 3 rows for VIN='XY123456' and
Row 1 shows Open Date 3/1/2019 and Invoice Date NULL, and
Row 2 shows Open Date 3/15/2019 and Invoice Date 3/28/2019, and
Row 3 shows Open Date 4/1/2019 and Invoice Date 4/5/2019,
I want to return Row 1 since the Invoice Date is NULL and it is the most recent Open Date for that VIN.
Had there been an Invoice Date for Row 1, we would return the row with the most recent date from either date column.
I have tried ELSE clause and COALASCE without success. I also tried doing a subquery to use MAXDATE.
SELECT RO.[RepairOrderID]
,RO.[CompanyName]
,CUS.CustomerKey
,UN.UnitNumber AS 'UNIT #'
,ISNULL(UC.[Tag #],'') AS 'S #'
,UN.Year
,UN.Make
,UN.Model
,UN.VIN
,ROS.[RepairOrderStatus] AS 'STATUS'
,RO.RepairOrderNumber AS 'RO #'
,CONVERT(VARCHAR(2),DATEPART(month, RO.[OpenDate]))
+ '/'+ CONVERT(VARCHAR(2),DATEPART(DAY, RO.[OpenDate]))
+ '/' + CONVERT(VARCHAR(4),DATEPART(YEAR, RO.[OpenDate]))
'OPEN DATE'
,CONVERT(VARCHAR(2),DATEPART(month, ROI.InvoiceDate))
+ '/'+ CONVERT(VARCHAR(2),DATEPART(DAY, ROI.InvoiceDate))
+ '/' + CONVERT(VARCHAR(4),DATEPART(YEAR, ROI.InvoiceDate))
'INVOICE DATE'
FROM [ProfitMaster].[dbo].[RepairOrder] RO with (nolock)
INNER JOIN [ProfitMaster].[dbo].[vwAC_SSR_Customer] CUS with (nolock)
ON CUS.CustomerID = RO.CustomerID
INNER JOIN [ProfitMaster].[dbo].[RepairOrderStatus] ROS with (nolock)
ON ROS.RepairOrderStatusID = RO.RepairOrderStatusID
LEFT OUTER JOIN [ProfitMaster].[dbo].[RepairOrderInvoice] ROI with (nolock)
ON ROI.RepairOrderID = RO.RepairOrderID
LEFT OUTER JOIN [ProfitMaster].[dbo].[vwSR_SSR_Unit] UN with (nolock)
ON UN.UnitInventoryID = RO.UnitInventoryID
LEFT OUTER JOIN [ProfitMaster].[dbo].[vwSR_SSR_UnitCharacteristics] UC with (nolock)
ON UC.UnitInventoryID = Ro.UnitInventoryID
WHERE ((ROS.RepairOrderStatus IN ('OPEN')
OR (ROS.RepairOrderStatus = 'QUOTE' AND RO.OpenDate >= (getDate()- 90)))
OR (ROS.RepairOrderStatus = 'INVOICED' AND ROI.InvoiceDate > '2019-01-01 00:00:00.000'))
AND (CUS.InternalAccount = '0' AND CUS.InternalLRCustomer = '0')
Results Sample:

Related

MS Access: match XRate to date

I have three tables: Sales, Currency, Exchange Rate
I need the appropriate exchange rate for every sale and foreign currency transaction to be calculated to our local currency. The Exchange Rate Table has values for each foreign currency, but only for one date in each month, the last day.
I have attempted the following thus far, which works, if the sales date happens to be exactely the last day of a month:
SELECT
qry_SALES.Payment_ID,
qry_SALES.Product_Name,
qry_SALES.Sales,
qry_SALES.SalesDate,
qry_SALES.SalesCcy,
tbl_XRate.XRate_CHF,
tbl_XRate.XDate
FROM
qry_SALES INNER JOIN
(tbl_Currency INNER JOIN tbl_XRate ON tbl_Currency.Currency_ID = tbl_XRate.Currency_ID)
ON (qry_SALES.SalesDate = tbl_XRate.XDate) AND (qry_SALES.SalesCcy = tbl_Currency.Ccy)
ORDER BY qry_SALES.SalesDate;
How do I get transactions that are during a month to match up with the exchange rate table's last value?
Try this using the matching ultimo date of the month:
FROM
qry_SALES
INNER JOIN
(tbl_Currency
INNER JOIN tbl_XRate
ON tbl_Currency.Currency_ID = tbl_XRate.Currency_ID)
ON (DateSerial(Year(qry_SALES.SalesDate), Month(qry_SALES.SalesDate) + 1, 0) = tbl_XRate.XDate)
AND (qry_SALES.SalesCcy = tbl_Currency.Ccy)
or:
FROM
qry_SALES
INNER JOIN
(tbl_Currency
INNER JOIN tbl_XRate
ON tbl_Currency.Currency_ID = tbl_XRate.Currency_ID)
ON (qry_SALES.SalesCcy = tbl_Currency.Ccy)
WHERE
DateSerial(Year(qry_SALES.SalesDate), Month(qry_SALES.SalesDate) + 1, 0) = tbl_XRate.XDate

How to sum a count of bookings to display total bookings for location and total value for location

I am writing a report that needs to show the number of bookings taken for a location with the total value of those bookings.
How do I sum the bookings column and show only one row for the location, that includes the columns set out in the example of expected data?
Select Statement Below:
SELECT
Locations.Description as LocationsDesc,
Locations.LocationGUID,
Venues.VenueName,
Venues.VenueGUID,
count (Bookings.BookingID) as Bookings,
Departments.DepartmentName,
Departments.DepartmentGUID,
sum(SalesTransactionDetails.NetDetailValue) as NetDetailValue,
sum(SalesTransactionDetails.DetailValue) as DetailValue,
SUM(CASE When Salestransactionlines.itemtype = 1 Then SalesTransactionDetails.NetDetailValue Else 0 End ) as RentalFee,
SUM(CASE When Salestransactionlines.itemtype = 2 Then SalesTransactionDetails.NetDetailValue Else 0 End ) as ExtraFee,
SalesTransactions.SalesTransactionGUID
FROM BookingLinesDetails
INNER JOIN Bookings ON BookingLinesDetails.BookingGUID=Bookings.BookingGUID
INNER JOIN Locations ON BookingLinesDetails.LocationGUID=Locations.LocationGUID
INNER JOIN Venues on Venues.Venueguid = Locations.Venueguid
INNER JOIN SalesTransactionDetails ON BookingLinesDetails.BookingLinesDetailGUID=SalesTransactionDetails.BookingLinesDetailGUID
INNER JOIN SalesTransactionLines ON SalesTransactionDetails.SalesTransactionLineGUID=SalesTransactionLines.SalesTransactionLineGUID
INNER JOIN SalesTransactions ON SalesTransactionLines.SalesTransactionGUID=SalesTransactions.SalesTransactionGUID
INNER JOIN Departments on Departments.DepartmentGUID = Locations.DepartmentGUID
WHERE
BookingLinesDetails.StartDateTime >= dbo.InzDateOnly(#pFromDate) and
BookingLinesDetails.StartDateTime < DateAdd(day,1,dbo.inzDateOnly(#pToDate)) and
Departments.DepartmentGUID in (Select GUID from dbo.InzSplitGUID(#DepartmentID)) and
(#IncludeAllLocationGroupsInVenues <> 0 or (#IncludeAllLocationGroupsInVenues = 0 )) and
Venues.VenueGUID in (Select GUID from dbo.InzSplitGUID(#VenueID)) and
salesTransactions.Status = 1 and -- remove cancelled
salestransactions.receiptonly = 0
GROUP BY
Locations.Description,
Locations.LocationGUID,
Venues.VenueName,
Venues.VenueGUID,
Departments.DepartmentName,
Departments.DepartmentGUID,
SalesTransactions.SalesTransactionGUID
The output is currently:
Desired output is:
LocationsDesc LocationGUID VenueGUID Bookings DepartmentName NetDetailValue DetailValue ExtraFee
Location - Deck Room 348A43F12 7DAD77BE 33 Aquatics Centre 2059.46 2162.5 0
I have attempted several versions of Count and sum. I believe I need to make the query a derived table and then select from that, but am not sure how to go about it, even if that is the answer.
Thank you in advance.

SQL Select Where Between statement missing results that should be there?

I apologize if this question has already been asked, but I couldn't find anything on it.
Basically, my accounting department runs a report every month to pull up all orders from a specific client for the previous month. My problem is that I have orders that are not showing up in these reports. The only similarities I can find in the orders that are missing is that if there are 2 or more sequential order numbers, one or more of them will not be picked up by the report if most other fields are the same.
When I ran the report over a single 24 hour period, any orders that were missing from the month-long report would show up for that day.
This is the code I'm using for the query:
SELECT paydetail.ord_hdrnumber as ord_hdrnumber,
NULL As TotalRevenue,
paydetail.pyt_itemcode As Item,
NULL As ItemRevenue,
pyd_amount As ItemPay,
paydetail.asgn_type,
paydetail.asgn_id, ord_driver1,
ord_revtype1, pyt_description As ItemDesc,
pyt_basis As ItemBasis
FROM paydetail
LEFT OUTER JOIN payheader ON pyh_pyhnumber = pyh_number
JOIN orderheader on orderheader.ord_hdrnumber = paydetail.ord_hdrnumber
JOIN paytype on paytype.pyt_itemcode = paydetail.pyt_itemcode
WHERE ord_billto = #billto
AND ord_startdate BETWEEN #startdate + ' 00:00:00' AND #enddate + ' 23:59:59'
AND paydetail.pyt_itemcode NOT IN ('TCKEVE','TCKEXP','TCKDEB')
UNION ALL
SELECT invoicedetail.ord_hdrnumber as ord_hdrnumber,
ivh_totalcharge As TotalRevenue,
invoicedetail.cht_itemcode As Item,
ivd_charge As ItemRevenue,
NULL As ItemPay,
NULL As asgn_type,
NULL as asgn_id,
NULL as ord_driver1,
ord_revtype1,
[cht_description] As ItemDesc,
[cht_basis] As ItemBasis
FROM invoicedetail
LEFT OUTER JOIN invoiceheader ON invoiceheader.ivh_hdrnumber = invoicedetail.ivh_hdrnumber
JOIN orderheader on orderheader.ord_hdrnumber = invoicedetail.ord_hdrnumber
JOIN chargetype ON chargetype.cht_itemcode = invoicedetail.cht_itemcode
WHERE ivh_billto = #billto
AND ord_startdate BETWEEN #startdate + ' 00:00:00' AND #enddate + ' 23:59:59'
ORDER by ord_hdrnumber

Return First 4 Rows, then Repeat for Grouping

I am trying to return data that will ultimately populate a label.
Each label is going onto a box, and the box can only have 4 items in it.
If a delivery has more than 4 items, then I need one label per 4.
Each row of data returned will populate one label, so if the delivery contains 9 items, then I need 3 rows of data returned.
Below is my current query, which is returning all items into a comma separated value using Stuff.
I want it so the first 4 rows for the delivery return in the first row, then the next 4 in the second and so on.
My Field LineOrd returns correctly if there are more than 4 lines on the dispatch.
select Distinct
delivery_header.dh_datetime,
delivery_header.dh_number,
order_header.oh_order_number as 'Order No',
order_header_detail.ohd_delivery_name,
order_header_detail.ohd_delivery_address1,
order_header_detail.ohd_delivery_address2,
order_header_detail.ohd_delivery_address3,
order_header_detail.ohd_delivery_town,
order_header_detail.ohd_delivery_county,
order_header_detail.ohd_delivery_postcode,
order_header_detail.ohd_delivery_country,
STUFF((Select ', '+convert(varchar(50),convert(decimal(8,0),DL.dli_qty))+'x '+OLI.oli_description
from delivery_header DH join delivery_line_item DL on DL.dli_dh_id = DH.dh_id join order_line_item OLI on OLI.oli_id = DL.dli_oli_id
Outer APPLY
(select
case when DelCurLine.CurLine <= 4
then '1'
Else
Case when DelCurLine.CurLine <= 8
then '2'
Else '3'
End
End +'-'+order_header.oh_order_number as LineOrd) as StuffLineOrder
Where DH.dh_id = delivery_header.dh_id And StuffLineOrder.LineOrd = LineOrder.LineOrd
FOR XML PATH('')),1,1,'') as Items,
LineOrder.LineOrd
from delivery_header
join delivery_line_item on delivery_line_item.dli_dh_id = delivery_header.dh_id
join order_line_item on order_line_item.oli_id = delivery_line_item.dli_oli_id
join order_header on order_header.oh_id = order_line_item.oli_oh_id
join order_header_detail on order_header_detail.ohd_oh_id = order_header.oh_id
join variant_detail on variant_detail.vad_id = order_line_item.oli_vad_id
join stock_location on stock_location.sl_id = order_line_item.oli_sl_id
Outer APPLY
(select count(DLI.dli_id) CurLine from delivery_line_item DLI where DLI.dli_dh_id = delivery_header.dh_id and DLI.dli_id <= delivery_line_item.dli_id)
as DelCurLine
Outer APPLY
(select
case when DelCurLine.CurLine <= 4
then '1'
Else
Case when DelCurLine.CurLine <= 8
then '2'
Else '3'
End
End +'-'+order_header.oh_order_number as LineOrd) as LineOrder
Outer APPLY
(select convert(varchar(50),convert(decimal(8,0),delivery_line_item.dli_qty))+'x '+order_line_item.oli_description as LineName) as LineName
where
delivery_header.dh_datetime between #DateFrom and #DateTo
and stock_location.sl_id = #StockLoc
and (order_header.oh_order_number = #OrderNo or #AllOrder = 1)
order by
delivery_header.dh_datetime,
delivery_header.dh_number,
order_header.oh_order_number,
order_header_detail.ohd_delivery_name,
order_header_detail.ohd_delivery_address1,
order_header_detail.ohd_delivery_address2,
order_header_detail.ohd_delivery_address3,
order_header_detail.ohd_delivery_town,
order_header_detail.ohd_delivery_county,
order_header_detail.ohd_delivery_postcode,
order_header_detail.ohd_delivery_country
You can use ROW_NUMBER() with a division by 4. This truncate the decimal because numerator is an interger. This give you group number with a maximum of four row in each group. You can then adjust your query to use this group number in a "group by" clause to return grouped rows into a single one.
Exemple here :
SELECT RawData.BoxGroup,
MIN(dh_datetime),
MIN(dh_number),
MIN(order_header.oh_order_number) as 'Order No'
--And so on
FROM
(SELECT BoxGroup = (ROW_NUMBER() OVER(ORDER BY (SELECT 1)) - 1) / 4,
*
FROM [TableNameOrQuery]) AS RawData
GROUP BY RawData.BoxGroup
Hope this help.

SQL Join returning all rows in a table

I am looking to get an account name from a table, but it is returning both rows in the table instead of the one that matches. Here's the table called LEDGERTRANS:
Account Date Voucher
402000 2014-01-14 CM-00011026
554500 2014-01-14 CM-00011026
This is being joined to a table called LEDGERTABLE which will match up the Account based on this tables account number. So we get a voucher number, then the account number, then match that to the table to get the account name. The thing is that this is bringing back BOTH account numbers descriptions from the table. Here's the SQL
SELECT DISTINCT
dbo.CUSTTABLE.NAME AS 'Customer',
dbo.CUSTINVOICEJOUR.INVOICEACCOUNT AS 'Acct #',
dbo.CUSTINVOICEJOUR.SALESID AS 'Sales Order',
dbo.CUSTINVOICEJOUR.INVOICEDATE AS 'Date',
dbo.CUSTINVOICEJOUR.INVOICEID AS 'Invoice',
(INVOICEAMOUNT - SALESBALANCE) AS 'Inv Amt',
'Misc Charge' AS ITEMID,
'Misc. Charge' AS 'Reason',
[DESCRIPTION] AS 'Division',
CREATEDBY
,LEDGERTABLE.ACCOUNTNUM as 'Account Number'
FROM
dbo.CUSTINVOICEJOUR INNER JOIN
dbo.CUSTINVOICETRANS ON dbo.CUSTINVOICEJOUR.INVOICEID = dbo.CUSTINVOICETRANS.INVOICEID INNER JOIN
dbo.CUSTTABLE ON ACCOUNTNUM = dbo.CUSTINVOICEJOUR.INVOICEACCOUNT INNER JOIN
dbo.DIMENSIONS ON NUM = dbo.CUSTINVOICEJOUR.DIMENSION2_
JOIN LEDGERTRANS ON LEDGERTRANS.VOUCHER = CUSTINVOICEJOUR.INVOICEID
inner JOIN LedgerTable ON LedgerTable.ACCOUNTNUM = Ledgertrans.ACCOUNTNUM
WHERE
dbo.CUSTINVOICEJOUR.INVOICEID LIKE 'CM-00%'
AND
dbo.CUSTINVOICEJOUR.INVOICEDATE BETWEEN #start AND #end
AND
dbo.CUSTINVOICEJOUR.DIMENSION2_ IN (#division)
AND
INVOICEAMOUNT <> SALESBALANCE
AND
CREATEDBY IN (#createdBy)
AND
LEDGERTRANS.CREDITING='0'
This effectively brings back 2 entries for each item. How can I get rid of this extra row?
C3 Ingenuity 110051 SO-00670938 CM-00011026 -33.750000000000 Misc Charge 402000
C3 Ingenuity 110051 SO-00670938 CM-00011026 -33.750000000000 Misc Charge 554500
even:
Select LEDGERTABLE.ACCOUNTNUM from LedgerTable JOIN Ledgertrans ON LedgerTable.ACCOUNTNUM = Ledgertrans.ACCOUNTNUM Where LEDGERTRANS.VOUCHER = CUSTINVOICEJOUR.INVOICEID
Returns both results
The difference is the last column (LEDGERTABLE.ACCOUNTNUM if I understand correctly).
You can exclude the table/column from the query, or GROUP BY the rest of columns leaving MIN/MAX from the exisitng account numbers