Dynamic Where Clauses for Dates - sql

Right now my code works, but it is not dynamic. Below shows the sum of daily values from a daily table in January 2022 compared to the monthly value from the monthly table for January 2022.
I am trying to figure out how to code this so the daily totals compared to the monthly can be pulled at anytime and I won't have to change the dates in the WHERE clauses everytime.
SELECT
b.LocationDescription AS 'Location'
,CONVERT(varchar, cm.RecordDate, 1) AS 'Month Date'
,DATENAME(month,cm.RecordDate) AS 'Month'
,SUM(cm.Production) AS 'Monthly Prod'
,d.total AS 'Daily Prod'
,SUM(cm.Production)-d.total AS 'Diff'
,(CASE WHEN d.total = 0 THEN 0 ELSE (SUM(cm.Production) - d.total)/d.total*100 END) AS 'Percent'
FROM CompletionMonthlyTb cm
INNER JOIN CompletionTb c ON cm.SystemID = c.SystemID
INNER JOIN LocationTb as b ON c.LocationID = b.LocationSystemID
JOIN (SELECT DISTINCT
b.LocationDescription AS 'Location'
,sum(cd.[Production]) AS 'Total'
FROM [xxxxxxx].[dbo].[LocationTb] b
JOIN xxxxxxxxx.dbo.CompletionTb c ON c.LocationID = b.LocationSystemID
JOIN xxxxxxx.dbo.CompletionDailyTb cd ON cd.SystemID = c.SystemID
WHERE cd.RecordDate BETWEEN '1-1-2022' AND '1-31-22'
GROUP BY b.LocationDescription) AS d ON d.Location = b.LocationDescription
WHERE cm.RecordDate = '2022-01-01'
GROUP BY b.LocationDescription, cm.RecordDate, d.total
ORDER BY cm.RecordDate, b.LocationDescription
RESULTS:
Location Month Date Month Monthly Prod Daily Prod Diff Percent
Alpha 01/01/22 January 27663 25584 2079 8
Beta 01/01/22 January 25503 26104 -600 -2

Related

SQL help to display no. of openings for all branches for each month of a year

Hi I need to generate a SSRS report to show how many centers got opened for each month in a calendar year under each branch. report will have 13 columns, first column being all the branches in each row and remaining 12 columns will have months of an year as header. I'm trying to get a result of each branch having no. of openings per month, so I can feed SSRS to display in tabular format. If a branch doesnt have any openings for any month, I need to display 0.
Branch table
=============
Branchid
Branchname
CenterOpen table
================
CenterOpenID
BranchID
CenterOpenDate
below is the SQL I had written
WITH months(MonthNumber) AS (
SELECT
1
UNION ALL
SELECT
MonthNumber + 1
FROM
months
WHERE
MonthNumber < 12
),
cteBranch(BranchID, BranchName, TargetOpenDate, Month, Count) as (
SELECT
B.BranchID,
B.BranchName,
CS.TargetOpenDate,
MONTH(CS.TargetOpenDate) as Month,
count(Month(CS.TargetOpenDate)) as Count
FROM
Branch B
left join goal.CenterOpenSchedule CS ON CS.BranchID = B.BranchID
GROUP BY
B.BranchID,
B.BranchName,
CS.TargetOpenDate,
MONTH(CS.TargetOpenDate)
)
select
*
from
months
cross join cteBranch
order by
BranchID asc,
MonthNumber asc
If I use cross join, months are repeating for each branch, how to resolve this? your help is highly appreciated.
Not sure which database you are on.
There are different ways to extract month/year from date.
Based on your example SQL, I'm going to use MONTH()
select branchName,
count(case when month(centerOpenDate) = 1 then branchId end) Jan_Count
...
...
count(case when month(centerOpenDate) = 12 then branchId end) Dec_Count
from Branch b
join CenterOpen co
on (b.BranchId = co.BranchId)
where year(centerOpenDate) = <your year filter>
group by branchName
This will take care of your below requirements:
" first column being all the branches in each row and remaining 12 columns will have months of an year as header."
and also -
"If a branch doesnt have any openings for any month, I need to display 0."
Your question is not explicit, but you seem to want a single year -- so you need to filter on the year.
The rest is basically conditional aggregation:
select b.branchName,
sum(case when month(co.centerOpenDate) = 1 then 1 else 0 end) as jan,
sum(case when month(co.centerOpenDate) = 2 then 1 else 0 end) as feb,
. . .
sum(case when month(co.centerOpenDate) = 12 then 1 else 0 end) as dec
from Branch b join
CenterOpen co
on b.BranchId = co.BranchId
where year(co.centerOpenDate) = #year
group by b.branchName

Oracle SQL - Count, per month, how many times a site appears in the results

I'm not sure if I will explain this correctly so apologies in advance.
I'm looking to put together a report that shows the number of times a site (central_site.site_code & central_site.site_name) appears in a report and then total this up for each month with a grand total at the end. The date to summarize into month values is job.actual_start_date
What I'm looking for is something like:
Site Code Site Name April May June July August Total
1234 HIGH STREET 2 4 3 3 2 14
3093 4TH AVENUE 10 5 8 8 7 38
The code I have got so far to produce all the information that I would like summarizing in the format above is:
select
central_site.site_code,
central_site.site_name,
job.actual_start_date
from
central_site
inner join job on job.site_code = central_site.site_code
inner join job_type on job.job_type_key = job_type.job_type_key
inner join job_status_log on job.job_number = job_status_log.job_number
where
job_type.job_type_code = 'G012' and
job_status_log.status_code = '5200'
I just don't know the syntax / formulas to be able to total each site up per month and then provide a total for the year.
I think you want conditional aggregation:
select cs.site_code, cs.site_name,
sum(case when extract(month from ?.datecol) = 1 then 1 else 0 end) as jan,
sum(case when extract(month from ?.datecol) = 2 then 1 else 0 end) as feb,
. . .,
count(*) as year_total
from central_site cs join
job j
on j.site_code = cs.site_code join
job_type jt
on j.job_type_key = jt.job_type_key join
job_status_log jsl
on j.job_number = js.job_number
where jt.job_type_code = 'G012' and
jsl.status_code = '5200' and
?.datecol >= date '2018-01-01' and
?.datecol < date '2019-01-01'
group by cs.site_code, cs.site_name;
This is assuming that "number of times" is simply a count. Your question doesn't specify *what column is used to specify the date. So, that element needs to be filled in.

SUM and Grouping by date and material

Still learning SQL forgive me.
I have 3 tables. a material table, a material_req table and a material_trans table. I want to group by material and then group columns by year.
so it would be [material, 2019, 2018, 2017, 2016, total (total being the total qty used for each material.
I have tried to place the date in the select statement, and grouped by the date also. but then the returned result is a lot of the same material with a lot of dates. I only need the year. maybe try the same and return just the year?
SELECT material_req.Material
-- , Material_Trans_Date
, SUM(-1 * material_trans.Quantity) AS 'TOTAL'
,Standard_Cost
FROM
Material_Req inner join Material_Trans
ON
Material_Req.Material_Req = Material_Trans.Material_Req
LEFt JOIN Material
ON
Material.Material = Material_Req.Material
WHERE
material_trans.Material_Trans_Date between '20180101' AND GETDATE()
-- Material_Trans_Date between '20180101' AND '20181231'
-- Material_Trans_Date between '20170101' AND '20171231'
-- Material_Trans_Date between '20160101' AND '20161231'
GROUP BY
material_req.Material ,Standard_Cost
ORDER BY
Material_Req.Material, Standard_Cost
expected results should by grouped by material, 2019, 2018, 2017,2016, Standard_Cost. the years column will have the sum of qty for each material for that year.
results look like this current_results
If you are using SQL Server then you might try this:
SELECT material_req.Material
, SUM(CASE WHEN DATEPART(YEAR, Material_Trans_Date) = '2019' THEN material_trans.Quantity ELSE 0 END) [2019 TOTAL]
, SUM(CASE WHEN DATEPART(YEAR, Material_Trans_Date) = '2018' THEN material_trans.Quantity ELSE 0 END) [2018 TOTAL]
,Standard_Cost
FROM
Material_Req inner join Material_Trans
ON
Material_Req.Material_Req = Material_Trans.Material_Req
LEFt JOIN Material
ON
Material.Material = Material_Req.Material
WHERE
material_trans.Material_Trans_Date between '20180101' AND GETDATE()
GROUP BY
material_req.Material ,Standard_Cost
ORDER BY
Material_Req.Material, Standard_Cost

How can I SELECT rows with MAX(Column value)

SELECT
DATEPART(YEAR, tblGRN.GRNApproveDate) AS Year,
tblGRNMaterials.MaterialCode,
tblMaterial.MaterialDescription,
SUM(tblGRNMaterials.NetQty) AS Qty
FROM
tblGRN
INNER JOIN
tblGRNMaterials ON tblGRN.GRNNO = tblGRNMaterials.GRNNO
INNER JOIN
tblMaterial ON tblGRNMaterials.MaterialCode = tblMaterial.MaterialCode
WHERE
(tblGRN.GRNStoreID = 'RM_Main')
AND (tblGRN.GRNStatus = 1)
AND (CONVERT(DATE, tblGRN.GRNApproveDate) BETWEEN '2017-01-01' AND '2018-12-31')
GROUP BY
tblGRNMaterials.MaterialCode, tblMaterial.MaterialDescription,
DATEPART(YEAR, tblGRN.GRNApproveDate)
ORDER BY
tblGRNMaterials.MaterialCode
My output
Year MaterialCode MaterialDescription Qty
-------------------------------------------------------------
2017 LM/CCM/SO Cellulose C. Methyl 200.000
2018 LM/CCM/SO Cellulose C. Methyl 350.000
2017 LM/MAG/PW Magnesium Stearate 175.000
2018 LM/MAG/PW Magnesium Stearate 250.000
2017 LM/MCC/PW Micro Crystal Cellulose 75.000
2018 LM/MCC/PW Micro Crystal Cellulose 0.320
I need to select each year holding the maximum value of 'Qty', comparison with year 2017 and 2018
Result should be:
Year MaterialCode MaterialDescription Qty
----------------------------------------------------------
2018 LM/CCM/SO Cellulose C. Methyl 350.000
2018 LM/MAG/PW Magnesium Stearate 250.000
2017 LM/MCC/PW Micro Crystal Cellulose 75.000
First, I would write the query like this:
SELECT year(g.GRNApproveDate) AS Year, gm.MaterialCode,
m.MaterialDescription, SUM(gm.NetQty) AS Qty
FROM tblGRN g INNER JOIN
tblGRNMaterials gm
ON g.GRNNO = gm.GRNNO INNER JOIN
tblMaterial m
ON gm.MaterialCode = m.MaterialCode
WHERE g.GRNStoreID = 'RM_Main' AND
g.GRNStatus = 1 AND
g.GRNApproveDate >= '2017-01-01' AND
g.GRNApproveDate < '2019-01-01'
GROUP BY gm.MaterialCode, m.MaterialDescription, year(g.GRNApproveDate)
ORDER BY gm.MaterialCode;
Although not the most performant method, probably the simplest is:
SELECT TOP (1) WITH TIES, year(g.GRNApproveDate) AS Year, gm.MaterialCode,
m.MaterialDescription, SUM(gm.NetQty) AS Qty
FROM tblGRN g INNER JOIN
tblGRNMaterials gm
ON g.GRNNO = gm.GRNNO INNER JOIN
tblMaterial m
ON gm.MaterialCode = m.MaterialCode
WHERE g.GRNStoreID = 'RM_Main' AND
g.GRNStatus = 1 AND
g.GRNApproveDate >= '2017-01-01' AND
g.GRNApproveDate < '2019-01-01'
GROUP BY gm.MaterialCode, m.MaterialDescription, year(g.GRNApproveDate)
ORDER BY ROW_NUMBER() OVER (PARTITION BY gm.MaterialCode ORDER BY SUM(gm.NetQty) DESC);

SQL: Showing all the products for each month even when

I'm trying to create a query that shows me all the products for each month, but I get stuck, because if a product its not sold in a certain month it wont appear, and I want to pass the value from month to month progressive.
For example like in this Picture:
You can see that for February I've got OLD and ORD, but because in March and April there was no Products sold I can't see, neither in May because there was no OLD product sold it wont appear. I want for each month to have all products, even if in the beginning its null.
Something like that:
February 2015:
0-OIR, 2-OLD, 2-ORD
March 2015:0-OIR, 2-OLD, 2-ORD
April 2015:0-OIR, 2-OLD, 2-ORD
May 2015:1-OIR,2-OLD, 5-ORD
June 2015: 1-OIR, 2-OLD, 7-ORD
and so on this table goes until current date
The column from the left its Cumulative summing per product and in the right between year and month its Cumulative summing for all products.
The query looks like this.
select
sum(a.count) over (partition by [Product Name] ORDER BY Year,Month) as 'Sum Per Product'
,a.[Product Name]
,a.month
,a.Year
,sum(a.Count) OVER (ORDER BY Year,Month) as 'Cumulative Sum of all products'
,
case
a.Month
when 1 then 'January'
when 2 then 'February'
when 3 then 'March'
when 4 then 'April'
when 5 then 'May'
when 6 then 'June'
when 7 then 'July'
when 8 then 'August'
when 9 then 'September'
when 10 then 'October'
when 11 then 'November'
when 12 then 'December'
end [months]
from (
SELECT
count(COALESCE(p.ShortName + ' ' ,'No Product')) as 'Count'
,COALESCE(p.ShortName + ' ' ,'No Product') as 'Product Name'
,MONTH(m.CreatedDatetime) AS 'Month'
,YEAR(m.CreatedDatetime) AS 'Year'
FROM Request r
LEFT JOIN Contact c on r.ContactId = c.ID
LEFT JOIN Machine m on r.machineId = m.ID
LEFT JOIN MachineStatus ms on m.active = ms.ID
join machineProduct mp on m.Id=mp.MachineId
LEFT JOIN RequestProduct rp on r.ID = rp.RequestId
LEFT JOIN ProductVersion pv on pv.ID = rp.ProductVersionId
LEFT JOIN Product p on pv.ProductId = p.ID
WHERE
m.statusid in (1,2)
GROUP BY COALESCE(p.ShortName + ' ' ,'No Product'), YEAR(m.CreatedDatetime),MONTH(m.CreatedDatetime)) a
group by Month,Year,a.count,a.[Product Name]
Order by a.Year,a.Month,a.[Product Name],[months]
EDIT:
I've created a temporary table that looks like this but how can I connect it to my main query to retrieve the info from Temp Table + The 2 Columns Cumulative summing per product and Cumulative summing for all products.
The query looks like this
`Declare #temp table
(id int
,name nvarchar(40)
,yeari int
,monthi int
)
-
Insert into #temp (id,name,yeari,monthi) (Select prd.id,prd.shortname,mac.yeari,mac.monthi
from (Select id,shortname from Product where Product.Active=1) prd
cross join (select distinct year(m.createddatetime) as yeari
,month(m.createddatetime) as monthi
FROM machine m
) mac)`
The Output looks like this:
How can I connect them?