Group By Date and SUM int - Date formatting and Order - sql-server

I'm trying to get the SUM of the quantity sold on a day. I need the results to be in ORDER BY date. The query below gives me the exact result I need, except the date is not formatted to what I need.
SELECT CAST(Datetime AS DATE) AS 'date', SUM(quantity) as total_quantity
FROM Invoice_Itemized ii
INNER JOIN Invoice_Totals it ON it.Invoice_Number = ii.Invoice_Number
WHERE ii.ItemNum = '4011'
AND it.datetime > '05/15/2015'
GROUP BY CAST(Datetime AS DATE)
SELECT DATENAME(MM, datetime) + ' ' + CAST(DAY(datetime) AS VARCHAR(2)) AS [DD Month], SUM(quantity) as total_quantity
FROM Invoice_Itemized ii
INNER JOIN Invoice_Totals it ON it.Invoice_Number = ii.Invoice_Number
WHERE ii.ItemNum = '4011'
AND it.datetime > '05/15/2015'
GROUP BY DATENAME(MM, datetime) + ' ' + CAST(DAY(datetime) AS VARCHAR(2))
Results for the top query:
2015-05-15 91.43
2015-05-16 84.77
Results for the bottom query:
June 1 128.34
June 10 85.06
The top query gives me the information I need in the order I need it by.
The bottom query gives me the date format I need but in the wrong order.

If you really need to apply different formatting, you can do it using a derived table:
select
DATENAME(MM, [date]) + ' ' + CAST(DAY([date]) AS VARCHAR(2)) AS [DD Month],
total_quantity
from
(
SELECT CAST([Datetime] AS DATE) AS [date], SUM(quantity) as total_quantity
FROM Invoice_Itemized ii
INNER JOIN Invoice_Totals it ON it.Invoice_Number = ii.Invoice_Number
WHERE ii.ItemNum = '4011'
AND it.[datetime] > '05/15/2015'
GROUP BY CAST(Datetime AS DATE)
) as X
This way you can wrap to results into the derived table, and then apply rest of the operations on that.
I would assume this would work too, but can't test now:
SELECT DATENAME(MM, CAST([datetime] AS DATE)) + ' '
+ CAST(DAY(CAST([datetime] AS DATE)) AS VARCHAR(2)) AS [DD Month],
SUM(quantity) as total_quantity
FROM Invoice_Itemized ii
INNER JOIN Invoice_Totals it ON it.Invoice_Number = ii.Invoice_Number
WHERE ii.ItemNum = '4011'
AND it.[datetime] > '05/15/2015'
GROUP BY CAST([datetime] AS DATE)

Related

Adding the total number of distinct customers to a cte table in Microsoft SQL Server

I am using Microsoft SQL Server and am trying to achieve the following
Date
Distinct Customers last 30Days
2020-12-01
20000
2020-12-02
23000
What I am trying to get is that between 2020-11-01 and 2020-12-01 I had 20000 distinct customers.
I have created a cte table with the List of Dates as can be seen below:
WITH listdate AS
(
SELECT CAST('2020-11-01' AS datetime) DateValue
UNION ALL
SELECT DateValue + 1
FROM listdate
WHERE DateValue + 1 < getdate()
)
SELECT
cast(DateValue as date) as DateValue
FROM listdate d
Now I am trying to join the customer and usage table with the list of dates table, however, I am not getting the correct end result. The following is what I have tried doing:
WITH listdate AS
(
SELECT CAST('2020-11-01' AS datetime) DateValue
UNION ALL
SELECT DateValue + 1
FROM listdate
WHERE DateValue + 1 < getdate()
)
SELECT
cast(DateValue as date) as DateValue
,count(distinct case when m.CallDate between dateadd(dd,-30,cast(d.datevalue as date)) and cast(d.datevalue as date) then m.Customerid end) as Distinct_CID
FROM listdate d
join Usage m on d.DateValue=m.CallDate
left join Customer c on c.CustomerID=m.Customer
where c.customertype = 'type A'
group by d.DateValue
OPTION (MAXRECURSION 0)
Can someone maybe suggest a different way of how to solve such a query?
Thanks
I would go for a lateral join to bring the count of distinct customers for the last 30 days:
with listdate as (
select cast('20201101' as date) as datevalue
union all
select dateadd(day, 1, datevalue) from listdate where datevalue < cast(getdate() as date)
)
select ld.datevalue, x.cnt
from listdate ld
cross apply (
select count(distinct c.customerid) as cnt
from usage u
inner join customer c on c.customerid = u.customerid
where
c.customertype = 'type A'
and c.calldate >= dateadd(day, -29, datevalue)
and c.calldate < dateadd(day, 1, datevalue)
) x
option (maxrecursion 0)
Note that I simplified the parts related to dates: this uses proper literal dates and date arithmetics in the recursive query; the where clause of the subquery implements what I understand as the last 30 days (today + the preceding 29 days), and properly handles the time portion of calldate, if any.

How to count distinct values in SQL under different conditions?

I have a data that looks as below. I would like to count total number of products and create a table that summarize the count for different date range. Please see diagram below as an example. Here the quay I have:
SELECT(
SELECT Count(DISTINCT Product) FROM Table1 WHERE Date BETWEEN '01/01/2017 AND
'01/15/2017,
SELECT Count(DISTINCT Product) FROM Table1 WHERE Date BETWEEN '01/16/2017 AND
'01/31/2017,
);
But I get an error:
Incorrect syntax near ','
This will work
SELECT
(SELECT Count(DISTINCT Product) FROM Table1 WHERE Date BETWEEN '01/01/2017' AND
'01/15/2017'),
(SELECT Count(DISTINCT Product) FROM Table1 WHERE Date BETWEEN '01/16/2017' AND
'01/31/2017')
;
You have a few syntax errors in your SQL:
when using the BETWEEN statement, you must only put quotes around
each date. Don't include the AND in the quotes.
You need to put brackets around each of the inner SELECTS.
There is an extra comma at the end (before the closing bracket)
However, this query will not return values of 5 and 2, because you are specifying DISTINCT in each SELECT. That will give you only 3 and 2 because there are only 3 distinct values for Product (A/D/E) returned from the first query. Remove the distinct if you want the number of rows.
Finally, I recommend that you use the YYYY-MM-DD syntax when using date literals in your SQL. This removes any ambiguity about what is the date and the month. For example, 1/4/2017 could be 4 Jan or 1 April, depending on how your SQL Server was configured. If you specify 2017-04-01, then this will always be interpreted as 1 April, and 2017-01-04 will always be 4 Jan.
Simply :
SELECT
(SELECT COUNT(DISTINCT Product) FROM yourtable T1 WHERE Date BETWEEN '01/01/2017' AND '01/15/2017') C1,
(SELECT COUNT(DISTINCT Product) FROM yourtable T2 WHERE Date BETWEEN '01/16/2017' AND '01/31/201') C2
Outputs: 3 | 2
SELECT
(SELECT COUNT(*) FROM yourtable T1 WHERE Date BETWEEN '01/01/2017' AND '01/15/2017') C1,
(SELECT COUNT(*) FROM yourtable T2 WHERE Date BETWEEN '01/16/2017' AND '01/31/201') C2
Outputs : 5 | 2
If the last code doesn't work you need to use Convert and Cast:
Declare #tb table(product varchar(50),[Date] date)
insert into #tb
select 'A' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),4,2) as date) as [Date] union all
select 'A' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),4,2)as date) as [Date] union all
select 'D' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/5/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/5/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/5/2017' as date),110),4,2) as date) as [Date] union all
select 'E' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/6/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/6/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/6/2017' as date),110),4,2)as date) as [Date] union all
select 'E' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/10/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/10/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/10/2017' as date),110),4,2)as date) as [Date] union all
select 'D' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/25/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/25/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/25/2017' as date),110),4,2)as date) as [Date] union all
select 'A' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/30/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/30/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/30/2017' as date),110),4,2)as date) as [Date]
--Copy from here
select acnt as 'Count(01/01/2017-01/15/2017)',bcnt as 'Count(01/16/2017-01/31/2017)' from
(select count(1) as acnt from #tb where [Date] BETWEEN '01/01/2017' AND '01/15/2017') as a
left join
(select count(1) as bcnt from #tb where [Date] BETWEEN '01/16/2017' AND '01/31/2017') as b
On a.acnt != b.bcnt or a.acnt = b.bcnt
;WITH CTE(Product ,[Date])
As
(
SELECT 'A','1/1/2017' Union all
SELECT 'A','1/1/2017' Union all
SELECT 'D','1/5/2017' Union all
SELECT 'E','1/6/2017' Union all
SELECT 'E','1/10/2017' Union all
SELECT 'D','1/25/2017' Union all
SELECT 'A','1/30/2017'
)
SELECT SUM([Count Of between '1/1/2017' AND '1/15/2017']) AS [Count Of between (1/1/2017 AND 1/15/2017)]
,SUM([Count Of between '1/16/2017' AND '1/31/2017']) AS [Count Of between (1/16/2017 AND 1/31/2017)]
FROM (
SELECT COUNT(Product) OVER (
PARTITION BY [Date] ORDER BY Product
) AS [Count Of between '1/1/2017' AND '1/15/2017']
,ISNULL(NULL, '') AS [Count Of between '1/16/2017' AND '1/31/2017']
FROM cte
WHERE [Date] BETWEEN '1/1/2017'
AND '1/15/2017'
UNION ALL
SELECT ISNULL(NULL, '')
,COUNT(Product) OVER (
PARTITION BY [Date] ORDER BY Product
) AS [Count Of between '1/16/2017' AND '1/31/2017']
FROM cte
WHERE [Date] BETWEEN '1/16/2017'
AND '1/31/2017'
) Dt
OutPut
Count Of between (1/1/2017 AND 1/15/2017) | Count Of between (1/16/2017 AND 1/31/2017)
--------------------------------------------------------------------------------
5 2

SQL Server 2008 R2: Combine two queries for optimization

I have the following query to optimize.
Following used to get the details from the profit table.
First inner SELECT: in the first select statement I have to get the details from the profit table and assign the row number for each row.
Second inner SELECT: in the second select statement I have to do some calculation (sum).
Outer SELECT: And get the result by combining them on id and also do some manipulation with data.
Code:
SELECT
a.p_id, p_Name,
convert(varchar, a.EndDate, 107) EndDate,
convert(varchar, a.EndDate, 106) NewEndDate,
LTRIM(a.p_id)) + '' + REPLACE(LEFT(CONVERT(VARCHAR, a.EndDate, 106), 6) + '' + RIGHT(CONVERT(VARCHAR, a.EndDate, 106), 2), ' ', '') as Compo,
a.GP,
b.fpro FirstProfit,
(b.fpro - b.spro) prodiff,
a.Qtity * a.GP as Ov,
a.Qtity,
b.fproChanPer
FROM
(SELECT
p_Name, p_id,
EndDate,
GP, FirstProfit,
prodiff,
Qtity,
ROW_NUMBER() OVER (PARTITION By p_Name, p_id ORDER BY EndDate) Rown
FROM
tbl_profit) a,
(SELECT
p_id,
CAST(SUM(FirstProfit) AS DECIMAL(24,2)) fpro,
CAST(SUM(SecondProfit) AS DECIMAL(24,2)) spro,
CAST(CAST(SUM(prodiff) AS DECIMAL(24,2)) / CAST(SUM(SecondProfit) AS DECIMAL(24,2)) * 100 AS DECIMAL(24,2)) fproChanPer
FROM
tbl_profit
GROUP BY
p_id) b
WHERE
b.p_id = a.p_id
AND Rown = 1
My question: can I combine those two (alias a and b) inner SELECT statements for query optimization?
My attempt: I have tried by using the following query but getting different calculation result.
SELECT p_Name,
p_id,
EndDate,
GP,
FirstProfit,
prodiff,
Qtity
ROW_NUMBER()OVER (PARTITION By p_Name,p_id ORDER By EndDate ) Rown,
CAST(SUM(FirstProfit) AS DECIMAL(24,2)) fpro,
CAST(SUM(SecondProfit) AS DECIMAL(24,2)) spro,
CAST(CAST(SUM(prodiff) AS DECIMAL(24,2)) /CAST(SUM(SecondProfit) AS DECIMAL(24,2)) * 100 AS DECIMAL(24,2)) fproChanPer
FROM tbl_profit
GROUP By p_id,p_Name,EndDate,GP,FirstProfit,prodiff,Qtity
tbl_profit must have multiple P_Name for a single p_id , when you are grouping by p_id only you are getting correct aggregate value whereas because of multiple p_name for a single p_id when you are grouping by p_id and p_name your aggregate sum values are getting double for wherever single p_id has more than one p_name.
The way you written query to get Rown = 1 records in this case is perfect, thought still have scope to optimize I have done few things please check.
SELECT
a.p_id,
p_Name,
CONVERT(varchar, a.EndDate, 107) EndDate,
CONVERT(varchar, a.EndDate, 106) NewEndDate,
LTRIM(a.p_id) + '' + REPLACE(LEFT(CONVERT(varchar, a.EndDate, 106), 6) + '' + RIGHT(CONVERT(varchar, a.EndDate, 106), 2), ' ', '') AS Compo,
a.GP,
b.fpro AS FirstProfit,
(b.fpro - b.spro) prodiff,
a.Qtity * a.GP AS Ov,
a.Qtity,
b.fproChanPer
FROM (
SELECT
a.p_Name,
a.p_id,
a.EndDate,
a.GP,
a.FirstProfit,
a.prodiff,
a.Qtity,
ROW_NUMBER() OVER (PARTITION BY a.p_Name, a.p_id ORDER BY a.EndDate) Rown
FROM tbl_profit AS a WITH (NOLOCK)
) AS a
INNER JOIN
(
SELECT
b.p_id,
CAST(SUM(b.FirstProfit) AS decimal(24, 2)) fpro,
CAST(SUM(b.SecondProfit) AS decimal(24, 2)) spro,
CAST(CAST(SUM(b.prodiff) AS decimal(24, 2)) / CAST(SUM(b.SecondProfit) AS decimal(24, 2)) * 100 AS decimal(24, 2)) fproChanPer
FROM tbl_profit AS b WITH (NOLOCK)
GROUP BY b.p_id
) AS b
ON b.p_id = a.p_id
AND a.Rown = 1

How to join two select queries in SQL Server 2012

I have two queries. One query pulls the information based on the orders that have been scheduled to them in a day by employee. The other query pulls the number of orders that have been completed and paid in a day, along with the total amount of the revenue from the orders.
I have scraped the forums to get the code together to get these queries, but I need to have both queries joined together. I want to use this information in report builder once I get it done. It's probably simple for someone, but it's confusing me as I'm far from any sort of expert with SQL.
I only need one day at the moment, but found this code and modified for now and hope that I can use it in the future when needing week and month data.
Any help would be appreciated.
Query 1
declare #dt DATE = '20160823'
set DATEFIRST 7;
set #dt = dateadd(week, datediff(week, '19050101', #dt), '19050101');
;with dt as
(
select
Technician = (CASE emp_id
WHEN 'CW697' THEN 'Joe Biggs'
WHEN 'DZ663' THEN 'Mimi Cassidy'
END),
dw = datepart(weekday, DATE)
from
dbo.ordemps
where
date >= #dt and date <dateadd(day, 7, #dt)
),
x AS
(
select
Technician, dw = coalesce(dw,8),
c = convert(varchar(11), COUNT(*))
from
dt
group by
grouping sets((Technician), (Technician,dw))
)
select
Technician,
[Sun] = coalesce([1], '-'),
[Mon] = coalesce([2], '-'),
[Tue] = coalesce([3], '-'),
[Wed] = coalesce([4], '-'),
[Thu] = coalesce([5], '-'),
[Fri] = coalesce([6], '-'),
[Sat] = coalesce([7], '-'),
TOTAL =[8]
from
x
PIVOT
(MAX(c) FOR dw IN([1],[2],[3],[4],[5],[6],[7],[8])) as pvt;
Query 2
select
case
when grouping(d.m)=15 then 'Year ' + cast(max(d.y) as varchar(10))
when grouping(date)=15 then datename(m, max(DATE)) + ' ' + cast(max(d.y) as varchar(10))
else cast(cast([date] as date) as varchar(255))
end as DATE,
TotalOrders = /*sum(Amount)*/convert(varchar(11), COUNT(*)),
TotalSales = sum(Amount),
Technician = (CASE recv_by
WHEN 'CW697' THEN 'Joe Biggs'
WHEN 'DZ663' THEN 'Mimi Cassidy'
END)
from
ordpay
cross apply
(select
datepart(yy, [date]),
datepart(m, [date])
) d(y, m)
where
[DATE] >= dateadd(day, datediff(day, 1, getdate()), 0)
and [date] < dateadd(day, datediff(day, 0, getdate()), 0)
group by
recv_by, d.y, rollup (d.m, date)
order by
d.y desc, grouping(d.m), d.m, grouping(DATE), DATE
At the easiest level you can use can join sub-queries. Your example is a little trickier because you are using CTEs which can't go in the subquery. To get you going in the right direction it should generally look like this:
with cte1 as (),
cte2 as ()
select *
from (
select *
from tables
where criteria -- subquery 1 (cannot contain order by)
) a
join ( -- could be a left join
select *
from tables
where criteria -- subquery 2 (cannot contain order by)
) b
on b.x = a.x --join criteria
where --additional criteria
order by --final sort
where subquery 1 would be your query 1 from select Technician to the end
and subquery 2 would be everything from your query 2 except the order by.
For further information on joins see the MSDN documentation
Since you aren't going to research much it doesn't seem here's a clunky and quick way, and keeps it simple for you, without having to explain a lot if we were to join the queries together more elegantly.
The first set of code has 2 common table expressions (CTE). So, select those results into a temp. Notice the --addition here
....
select
Technician,
[Sun] = coalesce([1], '-'),
[Mon] = coalesce([2], '-'),
[Tue] = coalesce([3], '-'),
[Wed] = coalesce([4], '-'),
[Thu] = coalesce([5], '-'),
[Fri] = coalesce([6], '-'),
[Sat] = coalesce([7], '-'),
TOTAL =[8]
into #someTemp --Addition here
from
....
Do the same for your second query...
...
into #someOtherTemp --Addition here
from
ordpay
...
Then join them togehter...
select t1.someColumns, t2.someOtherColumns
from #someTemp t1
inner join #someOtherTemp t2 on t1.column = t2.column

How to show missing days in query which uses join on calendar table in SQL Server 2012

How do I show the missing days in the query below which uses a join on a calendar table in SQL Server 2012?
The values for the missing day should be 0.
;WITH g AS
(
SELECT calendar.year, calendar.month, calendar.day, calendar.MonthName,
CAST(calendar.day AS NVARCHAR(2)) + '.' + CAST(calendar.month AS NVARCHAR(2)) + '.' + CAST(calendar.year AS NVARCHAR(16))AS DayMonthAndYear,
calendar.MonthName + ' ' + CAST(calendar.year AS NVARCHAR(16)) AS MonthNameAndYear,
COUNT(profileviews.ID) AS total_profileviews
FROM core_Calendar AS calendar
LEFT JOIN members_ProfileViews AS profileviews
ON CONVERT(DATE, calendar.date) = CONVERT(DATE, profileviews.CreatedAt)
WHERE calendar.date >= CONVERT(DATE, '03.02.2015')
AND calendar.date <= CONVERT(DATE, '03.02.2016')
AND profileviews.MemberID = 10
GROUP BY calendar.year, calendar.month, calendar.day, calendar.MonthName
)
SELECT g.year, g.month, g.day, g.MonthName, g.DayMonthAndYear, g.MonthNameAndYear, total_profileviews,
SUM(g.total_profileviews) OVER (ORDER BY g.year,g.month,g.day ROWS UNBOUNDED PRECEDING) AS rt_profileviews
FROM g
ORDER BY g.year, g.month, g.day;
You need to move the profileviews.MemberID = 10 to the LEFT JOIN, since it's essentially converting it to an INNER JOIN:
WITH g AS
(
SELECT C.[year],
C.[month],
C.[day],
C.[MonthName],
CONVERT(VARCHAR(10),C.[date],104) AS DayMonthAndYear,
C.[MonthName] + ' ' + CAST(C.[year] AS NVARCHAR(16)) AS MonthNameAndYear,
COUNT(profileviews.ID) AS total_profileviews
FROM core_Calendar AS C
LEFT JOIN ( SELECT *
FROM members_ProfileViews
WHERE MemberID = 10) AS P
ON CONVERT(DATE, C.[date]) = CONVERT(DATE, P.CreatedAt)
WHERE C.[date] >= CONVERT(DATE, '03.02.2015',104)
AND C.[date] <= CONVERT(DATE, '03.02.2016',104)
GROUP BY C.[year], C.[month], C.[day], C.[MonthName]
)
SELECT g.[year],
g.[month],
g.[day],
g.[MonthName],
g.DayMonthAndYear,
g.MonthNameAndYear,
total_profileviews,
SUM(g.total_profileviews) OVER (ORDER BY g.[year],g.[month],g.[day] ROWS UNBOUNDED PRECEDING) AS rt_profileviews
FROM g
ORDER BY g.[year], g.[month], g.[day];

Resources