how to use count, case and Distinct together in sql server - sql-server

I want to create a statement but i not success to complete this. can you please take a look and let me know what i need to do to complete this. My problem due how to add these two part in my query.
I want to look at the last 30 days of orders for each DRV1NUM. If that driver has worked 0 days then say ‘NOT ACTIVE’. If the driver has worked more than 15 days then ‘FULL TIME’ and less than 15 days is ‘PART TIME’.
In this one, I want to look at the last 30 days of orders and compare the left(4) of DRIVERNUM to the entire DRIVERNUM. In some instances, we have drivers where there is a 5th letter after the left 4.I want to look at the last 30 days of orders and if the left(4) DRV1NUM has more than one DRV1NUM WHEN looking at all characters, then SAY ‘MASTER’
SELECT DISTINCT DRVLICNUM,DOB,COUNTRY,CREDITLIMIT,DRIVERNUM=LEFT(DRIVERNUM,4),
SSN,D.VEHICLE,PHN1,DRVLICST,HOST,VEHICLE_MC,
VEHICLE_DOT,BACK_APPROVED=CASE WHEN PROBDATE IS NOT NULL THEN 'YES' ELSE 'NO' END
-- CASE WHEN COUNT(DISTINCT O.DROPDATE)=0 IN LAST 30 DAYS THEN 'NOT ACTIVE' WHEN COUNT(DISTINCT O.DROPDATE)>15 IN LAST 30 DAYS THEN 'FULL TIME' WHEN COUNT(DISTINCT O.DROPDATE)>=1 AND <=15 THEN 'PART TIME' IN LAST 30 DAYS ELSE NULL AS DAYSWORKED,
-- --CASE WHEN COUNT(DISTINCT O.DRV1NUM OF LEFT(DRIVERNUM,4 )>0 IN LAST 30 DAYS OF ORDERS>1 THEN 'MASTER IC' ELSE NULL AS MASTER
/* ABOVE TWO STATEMENT I WANT TO ADD */
FROM DRIVER D
FULL OUTER JOIN orde_ O ON O.DRV1ID=D.DRIVERID
AND ISNUMERIC(DRIVERNUM)=1 and DRIVERNUM NOT IN ('1010')
Expected Output That i want
DRVLICNUM Employee DOB COUNTRY ACTIVESTATUS
---------------------------------------------------------
055243324 CONTRACTOR 1985-04-13 ATLANTA FULL TIME
Here the ActiveStatus is Active because the driver worked more than 15 days in past 15 days or if it will less then 15 days it will be 'Part Time'

I don't have access to google drive link which you shared.
However, you will have to use CTE (common table expression) to get count of days and then use it compute value of ActiveStatus column.
Try using below code:
;
WITH CTE1
AS(
SELECT D.DRIVERID,
COUNT(DISTINCT O.DROPDATE) AS DayCount
FROM DRIVER AS D
LEFT JOIN ORDER AS O ON D.DRIVERID=O.DRV1ID AND O.DROPDATE BETWEEN CONVERT(DATE,DATEADD(DAY,-30,GETDATE())) AND GETDATE()
WHERE ISNUMERIC(D.DRIVERNUM)=1 AND D.DRIVERNUM NOT IN ('1010')
GROUP BY D.DRIVERID
)
SELECT DRVLICNUM,DOB,COUNTRY,CREDITLIMI,...
CASE
WHEN DayCount=0 THEN 'NOT ACTIVE'
WHEN DayCount<=15 THEN 'PART TIME'
WHEN DayCount>=30 THEN 'FULL TIME'
END AS ACTIVESTATUS
FROM CTE1 AS C
JOIN DRIVER AS D ON C.DRIVERID=D.DRIVERID

here is two siple queries for the first one:
1) select order by dates and group by driver (if there no more than one order per day):
select o.DRIVERID
, count(*) as cnt
from orde_ o
where o.DROPDATE betwen GETDATE() AND DATEADD(DAY,-30,GETDATE())
group by o.DRIVERID
2) select drivers and join groupped orders
select case
when o.ctn >= 15 then 'FULL TIME'
when o.ctn > 0 then 'PART TIME'
else 'NOT ACTIVE'
end
, <other fields you want>
from DRIVER as D
left join <query above> as o
on o.DRIVERID = d.DRIVERID
for the second one:
select left(d.DRIVERID, 4), count(*) as cnt
from DRIVER as D
group by left(d.DRIVERID, 4)
having count(*) > 1
and just join it, if is not null then compare whole id's

Related

SQL NESTED JOIN ISSUES

I'm having a heck of a time getting my query to work properly. I have 3 tables (ORDERS, ORDERSITEMS, ORDERPAYMENTS) that I'm trying to build a report for monthly sales taxes due which will look like this:
MONTH YEAR TOTAL RECEIPTS EXEMPT RECEIPTS NON-EXEMPT RECEIPTS SALES TAX
1 2020 $5,000 $4,500 $500 $31.25
TOTAL RECEIPTS: To get this number you have to add together all of the C.OrderPayments_Amount for the given time frame, in this case MONTH(C.OrderPayments_Date) = 1 AND YEAR(C.OrderPayments_Date) = 2020
EXEMPT RECEIPTS: You have to determine if an item is taxable (eg. digital files are not sales taxable, physical prints are). To get this you have determine if the item is taxable by checking the B.OrdersItems_ItemChargeSalesTax. If this field is 0 it does not get charged sales tax and if it is 1 then it does. You then have to filter to only get ORDERSITEMS for the Jan 2020 time frame using by grouping by the C.OrderPayments_Date column that have the B.OrdersItems_ItemChargeSalesTax = 0 and finally add the B.OrdersItems_Total together.
NON-EXEMPT RECEIPTS: To get this number you do the same exact thing for EXEMPT RECEIPTS above except you look for B.OrdersItems_ItemChargeSalesTax = 1 and add the B.OrdersItems_Total together.
SALES TAX: To get this number you use the same date filter as before MONTH(C.OrderPayments_Date) = 1 AND YEAR(C.OrderPayments_Date) = 2020 and then add the A.Order_SalesTax column together.
The first query I have listed is working fine to bring me the total taxes paid and the total income for the month (right now I have hard coded the WHERE statement but that is going to be applied via filters on my list page). What I
need to get from the ORDERSITEMS table is a field called ORDERSITEMS_ItemTotal and sum that field so it is a single line entry on the query. I have seen another person do a nested join. Any suggestions would be greatly appreciated.
**ORDERS TABLE "A"**
Order_ID,
Order_SalesTax,
stateTaxAbbreviation
**ORDERSITEMS TABLE "B"**
Order_FK,
OrdersItems_ItemChargeSalesTax,
OrdersItems_Total
NOTE: In the ORDERSITEMS table a single Order_FK may appear several times as there can be many items on an order
**ORDERPAYMENTS TABLE "C"**
Order_FK,
OrderPayments_PaymentDate,
OrderPayments_Amount
NOTE: In the ORDERPAYMENTS table a single Order_FK may appear several times as there can be multiple payments on an order
While writing this out it seems to be an easy task but when I attempt to put it all together the numbers are wrong because it is adding entries multiple times because there are multiple items on an order and thus it is adding the total payment every time.
Here is the code that I've been tinkering with and I would really appreciate any guidance. Thank you in advance and hopefully I've explained my situation clearly enough.
Select
a.stateTaxAbbreviation AS StateAbbr,
MONTH(c.OrderPayments_Date) AS PaymentMonth,
YEAR(c.OrderPayments_Date) AS PaymentYear,
SUM(c.OrderPayments_Amount) AS TotalPayments,
SUM(a.Order_SalesTax) AS sales_tax
FROM dbo.ORDERS a
INNER JOIN ORDERPAYMENTS as c ON c.Order_FK = a.Order_ID
LEFT OUTER JOIN ORDERITEMS b on b.Order_FK = a.Order_ID
WHERE a.stateTaxAbbreviation = 'MA' AND Month(b.OrderPayments_Date) = 1 AND YEAR(b.OrderPayments_Date) = 2020
GROUP BY stateTaxAbbreviation , MONTH(c.OrderPayments_Date), Year(c.OrderPayments_Date)
You should probably write 2 queries, one where you join the ORDERPAYMENTS table, and another where you join the ORDERITEMS table. Then you can combine them with UNION ALL.
Something like this:
SELECT StateAbbr,PaymentMonth,PaymentYear,SUM(TotalPayments),SUM(sales_tax),SUM(OrdersItems_Total)
FROM (
Select
a.stateTaxAbbreviation AS StateAbbr,
MONTH(c.OrderPayments_Date) AS PaymentMonth,
YEAR(c.OrderPayments_Date) AS PaymentYear,
SUM(c.OrderPayments_Amount) AS TotalPayments,
SUM(a.Order_SalesTax) AS sales_tax,
0 as OrdersItems_Total
FROM dbo.ORDERS a
INNER JOIN ORDERPAYMENTS as c ON c.Order_FK = a.Order_ID
WHERE a.stateTaxAbbreviation = 'MA' AND Month(c.OrderPayments_Date) = 1 AND YEAR(c.OrderPayments_Date) = 2020
GROUP BY stateTaxAbbreviation , MONTH(c.OrderPayments_Date), Year(c.OrderPayments_Date)
UNION ALL
Select
a.stateTaxAbbreviation AS StateAbbr,
MONTH(c.OrderPayments_Date) AS PaymentMonth,
YEAR(c.OrderPayments_Date) AS PaymentYear,
0 AS TotalPayments,
0 AS sales_tax,
SUM(B.OrdersItems_Total) as OrdersItems_Total
FROM dbo.ORDERS a
INNER JOIN ORDERITEMS b on b.Order_FK = a.Order_ID
WHERE a.stateTaxAbbreviation = 'MA' AND Month(b.OrderPayments_Date) = 1 AND YEAR(b.OrderPayments_Date) = 2020
GROUP BY stateTaxAbbreviation , MONTH(c.OrderPayments_Date), Year(c.OrderPayments_Date)
)t
GROUP BY StateAbbr,PaymentMonth,PaymentYear
Thanks to Wouter for pointing me in the right direction. After looking at his suggestion I went back and evaluated what I needed and I create the solution that worked that was based on his idea. Thanks for your patience Wouter, your insight helped a lot!
Select StateAbbr, OrderYear, OrderMonth, SUM(TotalSales) As TotalSales, SUM(TotalSales)-SUM(TaxableRevenue) As ExemptRevenue, SUM(TaxableRevenue) As TaxableRevenue, SUM(SalesTax) As SalesTax
FROM (
Select
/*Get Total Sales and Total Sales Tax Collected*/
a.stateTaxAbbreviation AS StateAbbr,
MONTH(a.Order_Date) As OrderMonth,
YEAR(a.Order_Date) As OrderYear,
SUM((a.Order_TotalBaseSale + a.Order_Shipping) - (((a.Order_PercentDiscount*a.Order_TotalBaseSale)/100) + a.Order_DollarDiscount)) As TotalSales,
SUM(0) As ExemptRevenue,
Sum(0) As TaxableRevenue,
SUM(a.Order_SalesTax) AS SalesTax
FROM dbo.ORDERS a
WHERE a.Order_Status != 'Cancelled'
Group By a.stateTaxAbbreviation, MONTH(a.Order_Date), YEAR(a.Order_Date)
UNION ALL
Select
/*GET EXEMPT ORDERS*/
a.stateTaxAbbreviation AS StateAbbr,
MONTH(a.Order_Date) As OrderMonth,
YEAR(a.Order_Date) As OrderYear,
Sum(0) As TotalSales,
Sum(OrdersItems_ItemTotal) AS ExemptRevenue,
Sum(0) AS TaxableRevenue,
Sum(0) As SalesTax
FROM ORDERSITEMS b
LEFT JOIN ORDERS a ON Order_ID = b.Order_FK
WHERE b.OrdersItems_ItemChargeSalesTax = 0 and a.Order_Status != 'Cancelled'
Group By a.stateTaxAbbreviation, MONTH(a.Order_Date), YEAR(a.Order_Date)
UNION ALL
Select
/*GET NON-EXEMPT ORDERS*/
a.stateTaxAbbreviation AS StateAbbr,
MONTH(a.Order_Date) As OrderMonth,
YEAR(a.Order_Date) As OrderYear,
SUM(0) As TotalSales,
SUM(0) AS ExemptRevenue,
Sum(OrdersItems_ItemTotal) AS TaxableRevenue,
Sum(0) As SalesTax
FROM ORDERSITEMS b
LEFT JOIN ORDERS a ON Order_ID = b.Order_FK
WHERE b.OrdersItems_ItemChargeSalesTax <> 0 and a.Order_Status != 'Cancelled'
Group By a.stateTaxAbbreviation, MONTH(a.Order_Date), YEAR(a.Order_Date)
)t
GROUP BY StateAbbr, OrderMonth, OrderYear
ORDER BY StateAbbr ASC, OrderYear DESC, OrderMonth ASC

Calculate the datediff() between the date 1 and 2

I need to calculate the datediff from one column where the in time marked with a 1 and the out time marked with a 2. if an employee swiped in and there is no out or out but there was no in i would like it to show as null.
I am not sure how I go about doing this.
SELECT
u.userid
,et.name
,CASE
WHEN scs.FullName is NULL THEN u.name
WHEN scs.FullName is NOT NULL THEN scs.FullName
END AS name
,e.LoggedTime AS SwipeTime
,CASE
WHEN et.name = 'Output On By Door' OR et.name = 'User Granted
Entry To Door Using Reading Device' THEN 1
ELSE 2
END AS SwipeTimeDiff
,d.name AS Door
FROM [Users] AS u
LEFT JOIN [Events] AS e ON e.RecordIndex1=u.UserID
LEFT JOIN [EventTypes] AS et on e.EventTypeID = et.EventTypeID
join .[Doors] AS d ON e.RecordIndex2 = d.DoorID
LEFT join SecurityContractorSignIn as scs on scs.Badge = u.lastname
WHERE LoggedTime > CONVERT(DATE, GETDATE()) and d.doorid in (32, 50, 42, 51, 33)
ORDER BY u.name,e.LoggedTime DESC
I would like to have a computed column with the time difference in days, hours and minutes or null if if there is a missing in(1) or out(2) time.
Well, the DATEDIFF() function is fully explained here and the difference for the specific datepart you want to extract is returned as an integer.
According to your need you may do something like but you will have the information in three (or more - if you want to extend) different columns:
-- Calculate the difference of how many days have passed
SELECT DATEDIFF(DAY, LoginTime, LogoutTime) AS DaysPassed
-- Calculate the difference of how many hours have passed
SELECT DATEDIFF(HOUR, LoginTime, LogoutTime) AS HoursPassed
-- Calculate the difference of how minutes have passed
SELECT DATEDIFF(MINUTE, LoginTime, LogoutTime) AS MinutesPassed
If you want to return a string whether the employee logged out or not you may use something like:
SELECT ISNULL(CONVERT(nvarchar(50), DATEDIFF(MONTH, '2019-01-04', NULL)), 'No logout')

Look at data in one date range and count from another date range

I'm stuck on a query where I am trying to get information on just customers that are newly acquired during a certain date range.
I had need to get a list of customers who placed their first order (of all time) in the first 6 months of the year. I then need to get total of their invoices, first invoice date, last invoice date, and count of orders for just the last 6 months.
I used a HAVING clause to ensure that I am just looking at customers that placed their first order in that 6 month period, but since we are past that period now, the total invoice info and order count information would include orders placed after this time. I considered including a restriction in the HAVING clause for the 'last invoice date', but then I am eliminating customers whose first order date was in the 6 month block, but also ordered after that. I'm not sure what to do next and am not having luck finding similar questions. Here is what I have so far:
SELECT c.customer, MAX(c.name) AS Name,
SUM(
CASE WHEN im.debit = 0
THEN im.amount * -1
ELSE im.amount
END
) AS TotalInvoiceAmount,
MIN(
im.date) AS FirstInvoiceDate,
MAX(
im.date) AS LastInvoiceDate,
COUNT(DISTINCT om.[order]) AS OrderCount
FROM invoicem im
INNER JOIN customer c ON im.customer = c.customer
FULL JOIN orderm om ON im.customer = om.customer
WHERE im.amount <> 0
GROUP BY c.customer
HAVING MIN(im.date) BETWEEN '01-01-2015' AND '06-30-2015'
ORDER BY c.customer
You can put the first 6 months qualification as a subquery. This would also work as a CTE
declare #startDate date = dateadd(month,-6,getdate())
SELECT c.customer, MAX(c.name) AS Name,
SUM(
CASE WHEN im.debit = 0
THEN im.amount * -1
ELSE im.amount
END
) AS TotalInvoiceAmount,
MIN(
im.date) AS FirstInvoiceDate,
MAX(
im.date) AS LastInvoiceDate,
COUNT(DISTINCT om.[order]) AS OrderCount
FROM invoice im
INNER JOIN (SELECT customer from invoice
GROUP BY customer
HAVING MIN(date) BETWEEN '01-01-2015'
AND '06-30-2015') im2
ON im.customer = im2.customer
INNER JOIN customer c ON im.customer = c.customer
FULL JOIN orderm om ON im.customer = om.customer
WHERE im.amount <> 0
AND im.date >= #startdate
GROUP BY c.customer
ORDER BY c.customer

Counting duplicate items in different order

Goal:
To know if we have purchased duplicate StockCodes or Stock Description more than once on difference purchase orders
So, if we purchase Part ABC on Purchase Order 1 and Purchase Order 2, it should return the result of
PurchaseOrders, Part#, Qty
Purchase Order1, Purchase Order2, ABC, 2
I just don't know how to pull the whole code together, more to the point, how do I know if it's occurred on more than 1 Purchase Order without scrolling through all the results , may also have to do with Multiple (Having Count) Statements as I only seem to be doing by StockCode
SELECT t1.PurchaseOrder,
t1.MStockCode,
Count(t1.MStockCode) AS SCCount,
t1.MStockDes,
Count(t1.MStockDes) AS DescCount
FROM PorMasterDetail t1
INNER JOIN PorMasterHdr t2
ON t1.PurchaseOrder = t2.PurchaseOrder
WHERE Year(t2.OrderEntryDate) = Year(Getdate())
AND Month(t2.OrderEntryDate) = Month(Getdate())
GROUP BY t1.PurchaseOrder,
t1.MStockCode,
t1.MStockDes
HAVING Count(t1.MStockCode) > 1
Using responses I came up with the following
select * from
(
SELECT COUNT(dbo.InvMaster.StockCode) AS Count, dbo.InvMaster.StockCode AS StockCodes,
dbo.PorMasterDetail.PurchaseOrder, dbo.PorMasterHdr.OrderEntryDate
FROM dbo.InvMaster INNER JOIN dbo.PorMasterDetail ON
dbo.InvMaster.StockCode = dbo.PorMasterDetail.MStockCode
INNER JOIN dbo.PorMasterHdr ON dbo.PorMasterDetail.PurchaseOrder = dbo.PorMasterHdr.PurchaseOrder
WHERE YEAR(dbo.PorMasterHdr.OrderEntryDate) = YEAR(GETDATE())
GROUP BY dbo.InvMaster.StockCode, dbo.InvMaster.StockCode,
dbo.PorMasterDetail.PurchaseOrder, dbo.PorMasterHdr.OrderEntryDate
) Count
Where Count.Count > 1
This returns the below , which is starting to be a bit more helpful
In result line 2,3,4 we can see the same stock code (*30044) ordered 3 times on different
purchase orders.
I guess the question is, is it possible to look at If something was ordered more than once within say a 30 day period.
Is this possible?
Count StockCodes PurchaseOrder OrderEntryDate
2 *12.0301.0021 322959 2014-09-08
2 *30044 320559 2014-01-21
8 *30044 321216 2014-03-26
4 *30044 321648 2014-05-08
5 *32317 321216 2014-03-26
4 *4F-130049/TEST 323353 2014-10-22
5 *650-1157/E 322112 2014-06-24
2 *650-1757 321226 2014-03-27
SELECT *
FROM
(
SELECT h.OrderEntryDate, d.*,
COUNT(*) OVER (PARTITION BY d.MStockCode) DupeCount
FROM
PorMasterHdr h
INNER JOIN PorMasterDetail d ON
d.PurchaseOrder = h.PurchaseOrder
WHERE
-- first day of current month
-- http://blog.sqlauthority.com/2007/05/13/sql-server-query-to-find-first-and-last-day-of-current-month/
h.OrderEntryDate >= CONVERT(VARCHAR(25), DATEADD(dd,-(DAY(GETDATE())-1),GETDATE()),101)
) dupes
WHERE
dupes.DupeCount > 1;
This should work if you're only deduping on stock code. I was a little unclear if you wanted to dedupe on both stock code and stock desc, or either stock code or stock desc.
Also I was unclear on your return columns because it almost looks like you're wanting to pivot the columns so that both purchase order numbers appear on the same line.

For LOOP in SQL Server

Total EmpId in Database = 74.
Active Days for September 2013 in Databse = 22
I want to segregate the dates when the employee was not filled the production in MIS_Opus table.
Since FULL OUTER Join was not worked, I m using the except query. Through this query, I can get the unfilled dates for each employee by passing the empid thru c# function. For that loop will going to SQL & back to C# for 74 times. Please let me know how can I get the unfilled dates for all employees at one shot in SQL itself. I m using SQL 2012 and VS 2012 c#.
Thank you,
select _Date from MIS_BM_Calendar c
where c.Month = 'September 2013' and c.DayShiftStatus = 'active'
except
select _Date from MIS_Opus o
where o.EmpId=#Empid
One way is to build a list of all employee + day combinations using a cross join. Then you can use a left join to check if there is an employee entry for that day.
select days._Date as TheDay
, emps.EmpId as EmployeeWithMissingEntry
from (
select distinct _Date
from MIS_BM_Calendar
where Month = 'September 2013'
and DayShiftStatus = 'active'
) days
cross join -- One row for each combination of employee and date
(
select distinct EmpId
from MIS_Opus
) emps
left join
MIS_Opus o
on o._Date = days._Date
and o.EmpId = emps.EmpId
where o._Date is null -- Employee entry for day not found

Resources