Dynamically Creating Column Counts Per Day of Month - sql

OK, so I have this query to find number of types per day like below. (Courtesy of MarkD here Counting Items/Rows in DB as Columns Grouped by Another Column)
select type,
sum(case when MyDate = '' then 1 else 0 end) as "10/1",
sum(case when MyDate = '' then 1 else 0 end) as "10/2
...etc
from MyTabe
group by type
However, I want to dynamically create date columns and have the count generated for each column, otherwise I would end up manually adding a new column for each day of the month.

I guess the best way to get the output I wanted was to do the following:
define startDate = to_date('2013-10-01', 'yyyy-mm-dd')
select type,
sum(case when MyDate = &&startDate then 1 else 0 end) as "1"
, sum(case when MyDate = &&startDate +1 then 1 else 0 end) as "2"
, sum(case when MyDate = &&startDate +2 then 1 else 0 end) as "3"
, sum(case when MyDate = &&startDate +3 then 1 else 0 end) as "4"
...etc for as many days of current month I am running
, sum(case when MyDate = &&startDate +29 then 1 else 0 end) as "30"
, sum(case when MyDate = &&startDate +30 then 1 else 0 end) as "31"--This would be commented out for Nov
from MyTabe
group by type
order by type
;
This way if I want to run this for Nov, Dec, Jan, and so on, I can just change the variable at the top and run the query. This is what I was looking for; however, I still wonder if it would be possible to generate the columns dynamically, but the more I look at it, the more I think that would require a pivot table.

Related

91/5000 How to show dates between a range and show the number of records in that range using SQLServer

I'm trying to generate a report and it must look like this:
My inicial data is 2019/08/01 and my final data is Today.
I have to show every date between this two dates, and then the amount of records. If there is no record, it must show zero.
So I tried:
SELECT M2.[Date], COUNT(1) AS 'qtd'
FROM [RM].[Mov] AS [m2]
WHERE [m2].[TipMovId] = 1
AND ([m2].[DataExercicio] BETWEEN '2019-07-31' AND GETDATE())
GROUP BY [m2].[DataPosse]
SELECT m2.[Date], COUNT(1) AS 'qtd2'
FROM [RM].[Mov] AS [m2]
WHERE [m2].[TipMovId] = 4
AND ([m2].[DataExercicio] BETWEEN '2019-07-31' AND GETDATE())
GROUP BY [m2].[DataExercicio]
And SQL returns me something like this:
How can I join the results and show all the dates in my period??
You can do something like this
SELECT M2.[Date],
sum(case when [m2].[TipMovId] = 1 then 1 else 0 end) AS 'qtd'
sum(case when [m2].[TipMovId] = 2 then 1 else 0 end) AS 'qtd2'
sum(case when [m2].[TipMovId] = 3 then 1 else 0 end) AS 'qtd3'
sum(case when [m2].[TipMovId] = 4 then 1 else 0 end) AS 'qtd4'
FROM [RM].[Mov] AS [m2]
WHERE
([m2].[DataExercicio] BETWEEN '2019-07-31' AND GETDATE()) GROUP BY [m2].[Date]

Condition SUM in SQL

I want to calculate con_Amount field & want to put total to D01,D02,....D31 on the condition of Con_PubDate.
if Con_PubDate field Day = 1 then I want to put the total to D01,if Con_PubDate field Day = 2 then I want to put the total to D02,likewise upto Day = 31 then I want to put the total to D31
I try following code in stored procedure but it had an error. Some one please help me to solve this problem.
SELECT Con_Cnt_Code,
Con_Dst_Code,
Con_Cor_Code,
SUM(CASE
WHEN DATEPART(DAY,Con_PubDate) = 1 THEN con_Amount
ELSE
SUM(CASE
WHEN DATEPART(DAY,Con_PubDate) = 2 THEN con_Amount
ELSE
SUM(CASE
WHEN DATEPART(DAY,Con_PubDate) = 31 THEN con_Amount
END) AS D31
END) AS D02
END) AS D01
FROM Contributions
GROUP BY Con_Cnt_Code,Con_Dst_Code,Con_Cor_Code
You probably want each conditional sum of a CASE expression as a separate item in your select list, something like this:
SELECT
Con_Cnt_Code,
Con_Dst_Code,
Con_Cor_Code,
SUM(CASE WHEN DATEPART(DAY,Con_PubDate) = 1 THEN con_Amount END) AS D01,
SUM(CASE WHEN DATEPART(DAY,Con_PubDate) = 2 THEN con_Amount END) AS D02,
-- and possibly other days as well
SUM(CASE WHEN DATEPART(DAY,Con_PubDate) = 31 THEN con_Amount END) AS D31
FROM Contributions
GROUP BY
Con_Cnt_Code, Con_Dst_Code, Con_Cor_Code;
By default, SUM will ignore NULL values, so you might not need an ELSE condition in your CASE expressions. If you add one, you may default the amount to sum to zero.

Sum by Distinct Values

I have the below code which brings though a sum of where a day 'GRLastDt' has complete or not complete however I hadn't accounted for duplicated Return IDs. Is there a way to return a sum by day for each Return ID?
For example day 24/5/15 may have 5 Lines to the day which have 'X' in Complete however 2 lines have duplicated return ids 'RtnId' and therefore the sum total would be 4 rather than 5 for 24/5/15.
SELECT
CONVERT(varchar(15), GRLastDt, 111) AS Date_,
SUM(CASE WHEN Complete = 'X' THEN 1 ELSE 0 END) AS Complete,
SUM(CASE WHEN Complete <> 'X' /*and RtnDt <>GRLastDt*/THEN 1 ELSE 0 END) AS Due
FROM [dbo].[vw_AN_Admin_VendorReturns]
WHERE (GRLastDt >= GETDATE() - 30)
GROUP BY CONVERT(varchar(15), GRLastDt, 111),GRLastDt
If I understand your problem right I think you can change this line:
SUM(CASE WHEN Complete = 'X' THEN 1 ELSE 0 END) AS Complete,
to this:
COUNT(DISTINCT CASE WHEN Complete = 'X' THEN RtnId END) AS Complete,
You probably want the same change for the Due calculation.

SQL percentage with rows same table with different where condition

I want to do a query like:
select
count(asterisk) where acción='a'/count(asterisk) where acción='b' * 100
from
same_table
grouped by day
but I don't want use subquery, is it possible with joins?
I`m not sure the syntax is correct, but you can use something like this:
SELECT day,
SUM(CASE WHEN "acción" = 'a' THEN 1 ELSE 0 END) AS SUM_A,
SUM(CASE WHEN "acción" = 'b' THEN 1 ELSE 0 END) AS SUM_B,
SUM(CASE WHEN "acción" = 'a' THEN 1 ELSE 0 END) AS SUM_A / SUM(CASE WHEN "acción" = 'b' THEN 1 ELSE 0 END) * 100 AS result
FROM your_table
GROUP BY day
The concept is to actually sum the the values that you need, instead of count.

SQL - Pivot/Unpivot?

I have a table in SQL Server 2008 in the format as below(simplified format) :
Date Miles Cost
I want to get a result like
Previous Week Current Week Variance
Miles
Cost
How can I achieve this? Do I need pivot/unpivot or what is the easiest and performance effective way to achieve this. Thanks.
SELECT 'Miles' AS Type, SUM(CASE WHEN date = lastweek THEN miles ELSE 0 END) as lastweek
, SUM(CASE WHEN date = thisweek THEN miles ELSE 0 END) as thisweek
SUM(CASE WHEN date = lastweek THEN miles ELSE 0 END) - SUM(CASE WHEN date = thisweek THEN miles ELSE 0 END) as variance
FROM yourtable
UNION
SELECT 'Cost' AS Type, SUM(CASE WHEN date = lastweek THEN cost ELSE 0 END) as lastweek
, SUM(CASE WHEN date = thisweek THEN cost ELSE 0 END) as thisweek
SUM(CASE WHEN date = lastweek THEN cost ELSE 0 END) - SUM(CASE WHEN date = thisweek THEN cost ELSE 0 END) as variance
FROM yourtable
This isn't 100% correct, but the syntax should be correct and should get you pretty close to what you're looking for