Orders list based on time period - sql-server

I have one table "orderdetails" table, I want Orders list from 06-01-2015 to 06-30- 15 per day below 60 orders based on time period like 00-01 and 01-02 like that
select
convert(datetime, Convert(varchar(50), OrderDate, 101)) as dateorder,
count(orderid) as ordercount
from
orderdetails
where
OrderDate between convert(datetime,Convert(varchar(50),'6/01/2015',101)) and convert(datetime,Convert(varchar(50),'06/30/2015',101))
and transactionid is not null
and DATEPART(HOUR,OrderDate) between '1' and '2'
group by
convert(datetime, Convert(varchar(50), OrderDate, 101))
having
count(orderid) < 60
But this query showing wrong list... its not displaying in count(orderid) < 60 orders its displaying overall orders, not below per day orders 60...

select * from (
select
convert(datetime, Convert(varchar(50), OrderDate, 101)) as dateorder,
count(orderid) as ordercount
from
orderdetails
where
OrderDate between convert(datetime,Convert(varchar(50),'6/01/2015',101)) and convert(datetime,Convert(varchar(50),'06/30/2015',101))
and transactionid is not null
and DATEPART(HOUR,OrderDate) between '1' and '2'
group by
convert(datetime, Convert(varchar(50), OrderDate, 101)) ) t
where ordercount < 60

Related

Combine two query and display in single line

I am using the below code to find the sales by credit card and cash and the current output show as below but I want to get the card and cash sales in single line.
current output:
expected output:
SELECT CONVERT(VARCHAR(10), CreateDate, 103) DT,SUM(AMOUNT),NULL FROM JnlDetails WHERE JnlDetails.CreateDate > '2021-05-01'
AND ACCOUNTID = '000153200101'
GROUP BY CONVERT(VARCHAR(10), CreateDate, 103)
UNION ALL
SELECT CONVERT(VARCHAR(10), CreateDate, 103) DT,NULL,SUM(AMOUNT) FROM JnlDetails WHERE JnlDetails.CreateDate > '2021-05-01'
AND ACCOUNTID = '000153200201'
GROUP BY CONVERT(VARCHAR(10), CreateDate, 103)
ORDER BY DT
Is there any other option available to achieve this without Union? Both the information's (Card and Sales) in the same table, based on the accountid we can split.
Using a case expression you can conditionally sum your values
select Convert(varchar(10), CreateDate, 103) DT,
Sum (case when ACCOUNTID = '000153200101' then AMOUNT end) as Cash,
Sum (case when ACCOUNTID = '000153200201' then AMOUNT end) as Card
from JnlDetails
where JnlDetails.CreateDate > '2021-05-01'
and ACCOUNTID in ('000153200101','000153200201')
group by Convert(varchar(10), CreateDate, 103)

Better way of calculating percentages of orders with ship times of over X days?

I'm writing a T-SQL query to calculate percentages of orders that have a ship time of over X days.
What I have now works but it feels clunky and I'm always looking to improve my query writing skills.
The first CTE is getting total orders from a time frame. The second CTE is getting any orders that have a ship date that is 3 days older (or less) than the order date.
;WITH TotalOrders
AS (
SELECT COUNT(*) AS TotalOrders
, MONTH(OrderDate) AS Month
, YEAR(OrderDate) AS Year
FROM Orders
WHERE OrderDate >= '2020-05-01'
GROUP BY MONTH(OrderDate), YEAR(OrderDate)
),
Under3
AS (
SELECT COUNT(*) AS Under3Days
, MONTH(OrderDate) AS Month
, YEAR(OrderDate) AS Year
FROM SorMaster SM
WHERE OrderDate >= '2020-05-01'
AND DATEDIFF(D, OrderDate, ShipDate) <= 3
GROUP BY MONTH(OrderDate), YEAR(OrderDate)
)
SELECT ROUND(Under3Days * 100.0 / TPO.TotalOrders, 1) AS 'PercentOfTotal'
, TPO.Month
, TPO.Year
FROM Under3
JOIN TotalOrders TPO
ON TPO.Month = Under3.Month
AND TPO.Year = Under3.Year
I know I can do this in temp tables too but wondering if there's a best practice to follow when doing these calculations
You can use conditional aggregation:
SELECT
ROUND(AVG(CASE WHEN ShipDate <= DATEADD(day, 3, OrderDate) THEN 100.0 ELSE 0 END), 1) AS PercentOfTotal
, MONTH(OrderDate) AS Month
, YEAR(OrderDate) AS Year
FROM Orders
WHERE OrderDate >= '2020-05-01'
GROUP BY MONTH(OrderDate), YEAR(OrderDate)

Add a row for every day between two dates with number of hours in SQL Server

Starting data:
Desired results something like this:
So it calculated the number of hours until the end of StartDateTime, if the EndDateTime is greater than end of day for StartDateTime. Then for every full day in between, it calculates 24 hours (this could stretch numerous days). And then when it gets to the EndDateTime - it calculates time from midnight (morning) to EndDateTime
I'm reading that I will probably need to use a recursive CTE, but I don't have any experience with recursions and am struggling.
this might get tricky, but I guess it can be solved using so called number table - i.e. table which has only one column populated with number sequence. In our case 0 based sequence.
The trick here is to get the number of days between start and end datetime. This value used in join between the data table and the numbers table will create the needed extra rows for each per day interval.
Of course we also have to setup properly start and end datetime of each day interval (CASE terms in the CTE)
Then we get for each per day interval number of minutes and divide by 60 to get proper decimal value.
Hope this helps.
Lets see the code:
-- input data
DECLARE #v_Dates TABLE
(
id varchar(20),
StartDateTime SMALLDATETIME,
EndDateTime SMALLDATETIME
)
INSERT INTO #v_Dates (id, StartDateTime, EndDateTime)
VALUES ('example 1', '02-17-2019 0:45', '02-19-19 12:30'),
('example 2', '02-21-2019 18:00', '02-22-19 12:15'),
('example 3', '02-22-2019 20:15', '02-22-19 20:30');
-- so called Number table which holds numbers 0 - 9999 in this case
DECLARE #v_Numbers TABLE
(
Number INT
);
-- populating the number table
INSERT INTO #v_Numbers
SELECT TOP 10000 ROW_NUMBER() OVER(ORDER by t1.number) - 1 as Number
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
-- we parse the dates into the per day intervals
;WITH IntervalsParsed(id, StartDateTime, EndDateTime, Number, IntervalStartDateTime, IntervalEndDateTime) AS
(
SELECT id
,StartDateTime
,EndDateTime
,Number
, InervalStartDateTime = CASE
WHEN D.StartDateTime > DATEADD(day, DATEDIFF(day, 0, D.StartDateTime), N.Number) THEN D.StartDateTime
ELSE DATEADD(day, DATEDIFF(day, 0, D.StartDateTime), N.Number)
END
, IntervalEndDateTime = CASE
WHEN D.EndDateTime < DATEADD(day, DATEDIFF(day, 0, D.StartDateTime), N.Number + 1) THEN D.EndDateTime
ELSE DATEADD(day, DATEDIFF(day, 0, D.StartDateTime), N.Number + 1)
END
FROM #v_Dates D
--this join basically creates the needed number of rows
INNER JOIN #v_Numbers N ON DATEDIFF(day, D.StartDateTime, D.EndDateTime) + 1 > N.Number
)
-- final select
SELECT id
, StartDateTime
, EndDateTime
, IntervalStartDateTime
, IntervalEndDateTime
, Number
, DecimalValue = CAST( DATEDIFF(minute, IntervalStartDateTime, IntervalEndDateTime) AS DECIMAL)/60
FROM IntervalsParsed
ORDER BY id, Number
Just another option is an ad-hoc tally table in concert with a CROSS APPLY
Example
Select A.[column1]
,A.[StartDateTime]
,A.[EndDateTime]
,Hours = sum(1) / 60.0
From #YourTable A
Cross Apply (
Select Top (DateDiff(MINUTE,[StartDateTime],[EndDateTime])+1)
D=DateAdd(MINUTE,-1+Row_Number() Over (Order By (Select Null)),[StartDateTime])
From master..spt_values n1,master..spt_values n2
) B
Group By [column1],[StartDateTime],[EndDateTime],cast(D as Date)
Returns
This may be little complicated, but here is one way to use recursive cte to get the output. You can add the start date with one day as long as it is less than end date of your column. Also declared a Static value to make sure we can get difference of 24 hours.
--Create a table
Select 'example1' exm, '2019-02-17 00:45:00' startdate, '2019-02-19 12:30:00' Enddate into #temp union all
Select 'example2' exm, '2019-02-21 18:00:00' startdate, '2019-02-22 12:15:00' Enddate union all
Select 'example3' exm, '2019-02-22 20:15:00' startdate, '2019-02-22 20:30:00' Enddate
Declare #datevalue time = '23:59:59'
;with cte as (select exm, startdate, enddate, case when datediff(day, startdate, enddate) = 0 then datediff(SECOND, startdate, enddate)
when datediff(day, startdate, enddate)>0 then
datediff(SECOND, cast(startdate as time), #datevalue)
end as Hoursn, cast(dateadd(day, 1,cast(startdate as date)) as smalldatetime) valueforhours from #temp
union all
select exm, startdate, enddate, case when datediff(day, valueforhours, enddate) = 0 then datediff(SECOND, valueforhours, enddate)
when datediff(day, valueforhours, enddate)>0 then datediff(SECOND, cast(valueforhours as time), #datevalue) end as Hoursn, case when datediff(day,valueforhours, enddate) > 0 then dateadd(day,1,valueforhours) end as valueforhours
from cte
where
valueforhours <= cast(enddate as date)
)
select exm, startdate, Enddate, round(Hoursn*1.0/3600,2) as [hours] from cte
order by exm
Output:
exm startdate Enddate hours
example1 2019-02-17 00:45:00 2019-02-19 12:30:00 23.250000
example1 2019-02-17 00:45:00 2019-02-19 12:30:00 24.000000
example1 2019-02-17 00:45:00 2019-02-19 12:30:00 12.500000
example2 2019-02-21 18:00:00 2019-02-22 12:15:00 6.000000
example2 2019-02-21 18:00:00 2019-02-22 12:15:00 12.250000
example3 2019-02-22 20:15:00 2019-02-22 20:30:00 0.250000

Temptable in SQL Server

Query #1:
SELECT a.*
INTO #TempTable1
FROM
(SELECT
Vendor,
CASE WHEN CONVERT(varchar(50), DateModified, 101)='01/01/1900' THEN '' ELSE CONVERT(varchar(50), DateModified, 101) END AS 'Date of Last Check',
CASE WHEN CONVERT(varchar(50), PaycommissionDate, 101)='01/01/1900' THEN '' ELSE CONVERT(varchar(50), PaycommissionDate, 101) END AS 'Date of check for month',
SUM([Original $ Total]) 'Amount'
FROM
Tbl_Commission_Reconcilation
WHERE
Vendor IS NOT NULL
AND MONTH([Order Date]) = MONTH (GETDATE())
GROUP BY
Tbl_Commission_Reconcilation.Vendor,
CONVERT(varchar(50), DateModified, 101),
[Sales Rep], PaycommissionDate) a
Output:
Vendor Date of Last Check Date of check for month Amount
-----------------------------------------------------------------------------
Boston Warehouse 12/12/2017 12/12/2017 919.00
Woodlink 12/12/2017 12/12/2017 979.86
Query #2:
SELECT b.*
INTO #TempTable2
FROM
(SELECT
[Sales Rep],
SUM([Commission $ paid]) 'Commission $ paid'
FROM
Tbl_Commission_Reconcilation
WHERE
Vendor IS NOT NULL
AND MONTH([Order Date]) = MONTH (GETDATE())
GROUP BY
[Sales Rep]) b
Output 2:
Sales Rep Commission $ paid
---------------------------------
Tammy Hanson 379.77
Final query:
select *
from #TempTable1, #TempTable2
Final output:
Vendor DateofLastCheck Dateofcheckformonth Amount Sales Rep Commpaid
Boston
Warehouse 12/12/2017 12/12/2017 919.00 Tammy Hanson 379.77
Woodlink 12/12/2017 12/12/2017 979.86 Tammy Hanson 379.77
Output 2 shows only one commission paid 379.77 for Tammy Hanson.But in final output shows 2 times commission paid 379.77.How to rectify this problem?
How to show only one commission paid in the final output?Please, any one helps me.
You are getting the duplicate values because you are using a Cross Join ( Cartesian Product) here. Please specify at least 1 condition to match the records from both tables so that the values will be displayed only against the desired records.
As per your current query, it will return all the possible combinations of rows in both tables. change it like this
select * from #TempTable1 T1,#TempTable2 T2 WHERE T1.ColumnName = T2.ColumnName
or you can also say
select * from #TempTable1 T1
inner join #TempTable2 T2
WHERE T1.ColumnName = T2.ColumnName
-- if you want records that have matches on both tables
or
select * from #TempTable1 T1
left join #TempTable2 T2
WHERE T1.ColumnName = T2.ColumnName
-- if you want records from #TempTable1 and display null for TempTable2 if no matching records
It appears you can just do one query. The larger query already has [sales rep] in the group by clause, so why not just sum the commission?
SELECT
a.* INTO #TempTable1
FROM (
SELECT
Vendor
, CASE WHEN CONVERT(varchar(50), DateModified, 101) = '01/01/1900' THEN '' ELSE CONVERT(varchar(50), DateModified, 101) END
AS 'Date of Last Check'
, CASE WHEN CONVERT(varchar(50), PaycommissionDate, 101) = '01/01/1900' THEN '' ELSE CONVERT(varchar(50), PaycommissionDate, 101) END
AS 'Date of check for month'
, SUM([Original $ Total]) 'Amount'
, [Sales Rep]
, SUM([Commission $ paid]) 'Commission $ paid'
FROM Tbl_Commission_Reconcilation
WHERE Vendor IS NOT NULL
AND MONTH([Order Date]) = MONTH(GETDATE())
GROUP BY
Tbl_Commission_Reconcilation.Vendor
, CONVERT(varchar(50), DateModified, 101)
, [Sales Rep]
, PaycommissionDate
) a
You should also add row_number to your queries
For Table1
SELECT a.*
INTO #TempTable1
FROM
(SELECT
Vendor,
CASE WHEN CONVERT(varchar(50), DateModified, 101)='01/01/1900' THEN '' ELSE CONVERT(varchar(50), DateModified, 101) END AS 'Date of Last Check',
CASE WHEN CONVERT(varchar(50), PaycommissionDate, 101)='01/01/1900' THEN '' ELSE CONVERT(varchar(50), PaycommissionDate, 101) END AS 'Date of check for month',
SUM([Original $ Total]) 'Amount',
ROW_NUMBER() OVER(ORDER BY Vendor, DateModified, [Sales Rep]) RN
FROM
Tbl_Commission_Reconcilation
WHERE
Vendor IS NOT NULL
AND MONTH([Order Date]) = MONTH (GETDATE())
GROUP BY
Tbl_Commission_Reconcilation.Vendor,
CONVERT(varchar(50), DateModified, 101),
[Sales Rep], PaycommissionDate) a
For Table 2
SELECT b.* INTO #TempTable2
from
(SELECT [Sales Rep],SUM([Commission $ paid]) 'Commission $ paid',
ROW_NUMBER() OVER(ORDER BY [Sales Rep]) RN
from Tbl_Commission_Reconcilation where Vendor is not null and Month([Order Date])= MONTH (Getdate())
group by [Sales Rep])b
and also left join table1 and table2 with this RN column
select
*
from #TempTable1 t1
LEFT JOIN #TempTable2 t2
ON t1.RN = t2.RN

Group By Month and Year to get distinct month and years then combine as a single date SQL

SELECT CONVERT(DATE,CAST([Year] AS VARCHAR(4))+'-'+
CAST([Month] AS VARCHAR(2))+'-'+
CAST('1' AS VARCHAR(2))) Date
FROM (SELECT YEAR(Date) as [Year], MONTH(Date) as [Month] FROM [dbo].[Data]
GROUP BY YEAR(Date), MONTH(Date)) x
ORDER BY Date DESC
Is there a better way to doinq this with a single query?
The query should return the unique month and year from a table but as combined Date.
IF OBJECT_ID ('tempdb..#TempT') IS NOT NULL DROP TABLE #TempT
CREATE TABLE #TempT(
dt datetime)
INSERT INTO #TempT (dt) VALUES
('2016-10-11'),
('2016-10-3'),
('2016-9-13'),
('2016-9-16')
SELECT DISTINCT CAST(DATEADD(month, DATEDIFF(month, 0, dt), 0) as DATE) AS Dates
from #TempT
Sample data is really a necessity for these kinds of questions, but this function could also be a help for you DATEFROMPARTS
SELECT
DATEFROMPARTS([Year], [Month], 01)
FROM
(
SELECT
YEAR(Date) as [Year],
MONTH(Date) as [Month]
FROM [dbo].[Data]
GROUP BY YEAR(Date), MONTH(Date)
) x
ORDER BY Date DESC
This code takes whatever date you enter and evaluates it as the first of the month. Effectively looking at only month and year:
SELECT
DATEADD(MM,DATEDIFF(MM,0, [Date] ),0) AS [YearMonth]
FROM [dbo].[Data]
ORDER BY
DATEADD(MM,DATEDIFF(MM,0, [Date] ),0)
;

Resources