How can I SELECT rows with MAX(Column value) - sql

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);

Related

Dynamic Where Clauses for Dates

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

How to get specific SQL counts for each year?

I am trying to get specific counts of bike sales per year, but now I'm only getting a total count of sales over the 5 year period and not broken up by specific years.
--CURRENT CODE:
Select datepart(year, C.TransactionDate) AS SalesYear,
SUM(COUNT(B.SerialNumber)) OVER() AS CountOfSerialNumber
FROM BIKE..Bicycle AS B
INNER JOIN BIKE..CustomerTransaction AS C on B.CustomerID = C.CustomerID
WHERE ModelType = 'Mountain' AND
TransactionDate BETWEEN '20000101' AND '20041231'
GROUP BY datepart(year, C.TransactionDate)
ORDER BY datepart(year, C.TransactionDate) ASC
--And my resulting output reads:
SalesYear | CountOfSerialNumber
2000 9431
2001 9431
2002 9431
2003 9431
2004 9431
You should be able to get the count without using SUM or OVER. OVER can be used to get a percentage of the total, if that's something you wanted to do.
SELECT DATEPART(YEAR, C.TransactionDate) AS SalesYear, COUNT(B.SerialNumber) AS Quantity,
COUNT(B.SerialNumber) * 100.0 / SUM(COUNT(B.SerialNumber)) OVER() AS Percentage
FROM BIKE..Bicycle AS B
INNER JOIN BIKE..CustomerTransaction AS C ON C.CustomerID = B.CustomerID
WHERE B.ModelType = 'Mountain' AND C.TransactionDate BETWEEN '20000101' AND '20041231'
GROUP BY DATEPART(YEAR, C.TransactionDate)
ORDER BY DATEPART(YEAR, C.TransactionDate) ASC

Current date and past 30 days total value

The code I currently have shows me the current value for everyday and gives the running total.
select t.lgl_entity_nm, d.date_key,
count(distinct s.site_key) AS Dis,
SUM(Dis) over (partition by t.lgl_entity_nm order by d.date_key ASC rows unbounded preceding) RunningTotal
from site_v s
join touchpoint_v t
on s.site_key = t.site_key
join omni_promo_varnt_fact_v o
on o.touchpoint_key = t.touchpoint_key
join date_v d
on d.date_key = o.date_key
where d.date_key between 20190901 and 20190931
and t.lgl_entity_nbr = 1
and tot_selected_qty > 0
and event_typ_cd in ('IS-SPRINT-T', 'IS-PRINT-T')
group by 1,2
Giving me this output:
lgl_entity_nm date_key dis runningtotal
Ahold USA 20190901 729 729
Ahold USA 20190902 733 1462
If you look at the date its set between a certain time period. What I want achieve is that it shows me the current date or any set date value and past 30 days total in a single row. Suppose the date is 2019-09-30:
lgl_entity_nm date_key(current date) dis total (past30 days)
Ahold USA 20190930 739 21953
Can this be achieved? If so how?
Try this?
DECLARE #CurrentDate DATE = GETDATE()
,#MonthBack DATE = DATEADD(DAY,-30,GETDATE())
SELECT t.lgl_entity_nm
,#CurrentDate AS CurrentDate
,COUNT(DISTINCT s.site_key) AS Dis
,SUM(Dis) AS RunningTotal
FROM site_v AS s
JOIN touchpoint_v AS t ON s.site_key = t.site_key
JOIN omni_promo_varnt_fact_v AS o ON o.touchpoint_key = t.touchpoint_key
JOIN date_v AS d ON d.date_key = o.date_key
WHERE d.date_key BETWEEN #MonthBack AND #CurrentDate
AND t.lgl_entity_nbr = 1
AND tot_selected_qty > 0
AND event_typ_cd IN ('IS-SPRINT-T', 'IS-PRINT-T')
GROUP BY
t.lgl_entity_nm
I think you can just remove the date key from the aggregation:
select t.lgl_entity_nm, max(d.date_key),
count(distinct s.site_key) as as RunningTotal
from site_v s join
touchpoint_v t
on s.site_key = t.site_key join
omni_promo_varnt_fact_v o join
on o.touchpoint_key = t.touchpoint_key join
date_v d
on d.date_key = o.date_key
where d.date_key between 20190901 and 20190931 and
t.lgl_entity_nbr = 1 and
tot_selected_qty > 0 and
event_typ_cd in ('IS-SPRINT-T', 'IS-PRINT-T')
group by 1;
Actually, this subtly different from your query, because you are not counting distinct site_key over the entire period, but adding up the distinct counts per day. For that:
count(distinct d.date_key || ':' || s.site_key) as RunningTotal

ORACLE query with percentage of total for categories and subcategories

Query :
SELECT Year, Month,Sector, Subsector, sum(employed), sum(unemployed)
FROM dbo.workforce
where Year= 2017 and Month = 12 and Sector = any('0700','0500','0600')
group by Year, Month,Sector, Subsector
over my table returns:
> Year,Month,Sector,Subsector,SUM(Employed),SUM(Unemployed)
> "2017","12","0700","0720","30089","2348"
> "2017","12","0600","0630","16778","781"
> "2017","12","0500","0000","7332","1198"
> "2017","12","0600","0620","3741","338"
> "2017","12","0700","0710","56308","4493"
> "2017","12","0600","0610","105492","21966"
I need to add columns for totals and percentages for sectors and subsectors in following way:
Year,Month,Sector,TotalSector,PercentageFromAllSectors,SubSector,TotalForSubsector,PercentageForSubsector
"2017","12","0700","6845","3,65","0720","2351","34,35"
"2017","12","0700","6845","3,65","0710","4494","65,65"
I guess I need 2 variables that will hold values for overall total and total for each sector and than calculate percentage for sectors and subsectors but I don'k now how to formulat that.
you could use a join
select a.Year, a.Month, a.Sector, a.Subsector, a.sum_employed
, (a.sum_employed/b.tot_employed)*100, a.sum_unemployed, (a.sum_unemployed/b.tot_unemployed)*100
from (
SELECT Year, Month,Sector, Subsector, sum(employed) sum_employed, sum(unemployed) sum_unemployed
FROM dbo.workforce
where Year= 2017 and Month = 12 and Sector = any('0700','0500','0600')
group by Year, Month,Sector, Subsector
) a
inner join (
SELECT Year, Month,Sector,sum(employed) tot_employed, sum(unemployed) tot_unemployed
FROM dbo.workforce
where Year= 2017 and Month = 12 and Sector = any('0700','0500','0600')
group by Year, Month,Sector
) b on a.Year = b.Year
and a.Month = b.Month
and a.Sector = b.Sector

How use the operator IN with a subquery that returns two columns

Hello masters I need your help.
Having the table:
DataCollection
==================
PK Code
smallint RestaurantCode
smallint Year
tinyint Month
money Amount
money AccumulativeMonthsAmount
...
I need the AccumulateAmount for the LastMonth on every Restaurant.
First, I get the last Month per Restaurant for the 'current year'(for this case):
SELECT RestaurantCode, MAX(Month) as Month FROM DataCollection
WHERE (Year >= 2012 AND YEAR <= 2012) GROUP BY RestaurantCode
Now I want to use that as subquery, to get the Last - AccumulativeMonthsAmount :
SELECT AccumulativeMonthsAmount FROM DataCollection
WHERE (RestaurantCode, Month)
IN (SELECT RestaurantCode, MAX(Month) as Month FROM DataCollection
WHERE (Year >= 2012 AND YEAR <= 2012) GROUP BY RestaurantCode)
But the operator IN, don't work, How I should do it?
Sample Data sorted by Year and Month:
RestCode Amount Accumulative Year Month
123 343.3 345453.65 2012 12
123 124.7 345329.00 2012 11
...
122 312.2 764545.00 2012 12
122 123.4 764233.00 2012 11
...
999 500.98 2500.98 2012 6
999 100.59 2000.00 2012 5
...
I wanna to get the Accumulative for the last month of every restaurant:
RestCode Accumulative Month
123 345453.65 12
122 764545.00 12
99 2500.98 6
...
SELECT dc.AccumulativeMonthsAmount
FROM dbo.DataCollection AS dc
INNER JOIN
(
SELECT RestaurantCode, MAX(Month)
FROM dbo.PAL_Entries_Relatives
WHERE [Year] = 2012
GROUP BY RestaurantCode
) AS r(rc, m)
ON dc.RestaurantCode = r.rc
AND dc.[Month] = r.m;
With the changed requirements:
;WITH x AS
(
SELECT RestCode, Accumulative, [Month],
rn = ROW_NUMBER() OVER (PARTITION BY RestCode ORDER BY [Month] DESC)
FROM dbo.DataCollection -- or is it dbo.PAL_Entries_Relatives?
)
SELECT RestCode, Accumulative, [Month]
FROM x
WHERE rn = 1
ORDER BY [Month] DESC, RestCode DESC;
That syntax is not allowed in SQL Server. You can do something similar with EXISTS:
SELECT AccumulativeMonthsAmount
FROM DataCollection dc
WHERE exists (select 1
from PAL_Entries_Relatives er
where (Year >= 2012 AND YEAR <= 2012)
group by RestaurantCode
having er.RestaurantCode = dc.RestaurantCode and
max(er.month) = dc.Month
)
SELECT AccumulativeMonthsAmount
FROM DataCollection
INNER JOIN PAL_Entries_Relatives
ON DataCollection.RestaurantCode = PAL_Entries_Relatives.RestaurantCode
WHERE (Year >= 2012 AND YEAR <= 2012)
GROUP BY DataCollection.RestaurantCode
HAVING AccumulativeMonthsAmount.Month = MAX(PAL_Entries_Relatives.Month)