I am working on an sql query where i will give a date from which Month and year will be determined. Then the record will be selected from Lab_Analysis and Lab_CSAnalysis table of any Furnace and Product ID. For this i Did following
Declare #Furnace varchar(50)='FUR-A'
Declare #Product bigint=1
Declare #sd date
Declare #ed date
Declare #Date date='02-02-2019'
SET #sd=(SELECT DATEADD(s,1,DATEADD(mm, DATEDIFF(m,0,#Date),0)))
SET #ed=(SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#Date)+1,0)))
;WITH dates AS (
SELECT #sd as theDate
UNION ALL
SELECT DATEADD(day, 1, theDate)
FROM dates
WHERE DATEADD(day, 1, theDate) <= #ed
)
SELECT DATEPART(dd, D.theDate) AS 'Day', ISNULL(LS.QtyMT, 0) AS QtyMt, ISNULL(SUM(L.Mn), 0) AS Mn, ISNULL(SUM(L.Si), 0) AS Si, ISNULL(SUM(L.P), 0) AS P,
ISNULL(LS.Carbon, 0) AS C, ISNULL(LS.Sulphur, 0) AS S, ISNULL(SUM(L.MnO), 0) AS MnO, ISNULL(SUM(L.CaO), 0) AS CaO, ISNULL(SUM(L.AI2O3), 0)
AS AI2O3, ISNULL(SUM(L.MgO), 0) AS MgO, ISNULL(SUM(L.Fe2O3), 0) AS Fe2O3, ISNULL(SUM(L.SiO2), 0) AS SiO2, ISNULL(SUM(L.Basicity), 0) AS Basicity
FROM Lab_Product AS LP INNER JOIN
Lab_Analysis AS L ON LP.ID = L.Product RIGHT OUTER JOIN
dates AS D ON L.Date = theDate LEFT OUTER JOIN
Lab_CSAnalysis AS LS ON LS.Date = L.Date AND (LP.ID = 1 AND L.Furnace = #Furnace AND LS.Furnace=#Furnace)
GROUP BY D.theDate, LS.QtyMT, LS.Carbon, LS.Sulphur
Here i want to view Record of Furnace='A' and ProductID=1. Then the above query is correct Output. There is no Record in Other than Furnace 'A' and Product ID=1. But when i want to View records of Furnace 'B' then it is still showing records of Furnace 'A'. How to solve this?
because of your filter on the left join. I made some changing over your query
Declare #Furnace varchar(50)='FUR-A'
Declare #Product bigint=1
Declare #sd date
Declare #ed date
Declare #Date date='02-02-2019'
SET #sd=(SELECT DATEADD(s,1,DATEADD(mm, DATEDIFF(m,0,#Date),0)))
SET #ed=(SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#Date)+1,0)))
;WITH dates AS (
SELECT #sd as theDate
UNION ALL
SELECT DATEADD(day, 1, theDate)
FROM dates
WHERE DATEADD(day, 1, theDate) <= #ed
)
SELECT DATEPART(dd, D.theDate) AS 'Day',
ISNULL(LS.QtyMT, 0) AS QtyMt,
ISNULL(SUM(L.Mn), 0) AS Mn,
ISNULL(SUM(L.Si), 0) AS Si,
ISNULL(SUM(L.P), 0) AS P,
ISNULL(LS.Carbon, 0) AS C,
ISNULL(LS.Sulphur, 0) AS S,
ISNULL(SUM(L.MnO), 0) AS MnO,
ISNULL(SUM(L.CaO), 0) AS CaO,
ISNULL(SUM(L.AI2O3), 0) AS AI2O3,
ISNULL(SUM(L.MgO), 0) AS MgO,
ISNULL(SUM(L.Fe2O3), 0) AS Fe2O3,
ISNULL(SUM(L.SiO2), 0) AS SiO2,
ISNULL(SUM(L.Basicity), 0) AS Basicity
FROM
dates
INNER JOIN Lab_Analysis AS L ON L.Date = dates.theDate AND L.Furnace = #Furnace
LEFT JOIN Lab_Product AS LP ON LP.ID = L.Product AND LP.ID = 1
LEFT JOIN Lab_CSAnalysis AS LS ON LS.Date = L.Date AND (L.Furnace = LS.Furnace)
GROUP BY
D.theDate, LS.QtyMT, LS.Carbon, LS.Sulphur
Related
My end goal is to see end of month data for previous month.
Our processing is a day behind so if today is 7/28/2021 our Process date is 7/27/2021
So, I want my data to be grouped.
DECLARE
#ProcessDate INT
SET #ProcessDate = (SELECT [PrevMonthEnddatekey] FROM dbo.dimdate WHERE datekey = (SELECT [datekey] FROM sometable [vwProcessDate]))
SELECT
ProcessDate
, LoanOrigRiskGrade
,SUM(LoanOriginalBalance) AS LoanOrigBalance
,Count(LoanID) as CountofLoanID
FROM SomeTable
WHERE
ProcessDate in (20210131, 20210228,20210331, 20210430, 20210531, 20210630)
I do not want to hard code these dates into my WHERE statement. I have attached a sample of my results.
I am GROUPING BY ProcessDate, LoanOrigRiskGrade
Then ORDERING BY ProcessDate, LoanOrigIRskGrade
It looks like you want the last day of the month for months within a specified range. You can parameterize that.
For SQL Server:
DECLARE #ProcessDate INT
SET #ProcessDate = (
SELECT [PrevMonthEnddatekey]
FROM dbo.dimdate
WHERE datekey = (
SELECT [datekey]
FROM sometable [vwProcessDate]
)
)
DECLARE #startDate DATE
DECLARE #endDate DATE
SET #startDate = '2021-01-01'
SET #endDate = '2021-06-30'
;
with d (dt, eom) as (
select #startDate
, convert(int, replace(convert(varchar(10), eomonth(#startDate), 102), '.', ''))
union all
select dateadd(month, 1, dt)
, eomonth(dateadd(month, 1, dt))
from d
where dateadd(month, 1, dt) < #endDate
)
SELECT ProcessDate
, LoanOrigRiskGrade
, SUM(LoanOriginalBalance) AS LoanOrigBalance
, Count(LoanID) as CountofLoanID
FROM SomeTable
inner join d on d.eom = SomeTable.ProcessDate
Difficult to check without sample data.
Hello I am working on a dataset for a report in SSRS
and I have a query which gives the total requests in the backlog :
SELECT
COUNT(*) as NB
FROM p_rqt WITH (NOLOCK)
INNER JOIN p_cpy WITH (NOLOCK) ON p_cpy.CpyInCde = p_rqt.OrigCpyInCde
WHERE
CpyTypInCde IN (27, 31)
AND p_rqt.RqtNatInCde IN (74, 75, 76)
AND HeadRqtInCde = 0
AND p_rqt.OrigCpyInCde LIKE CASE WHEN #Client = 0 THEN '%' ELSE #Client END
AND ((RcvDte < DATEADD(day, 1, #DateDeb) AND RqtEndDte IS NULL) OR
(RcvDte < DATEADD(day, 1, #DateDeb) AND RqtEndDte > DATEADD(day, 1, #DateDeb)))
and I want to retrieve the total amount left per day.
I tried lot of things like this :
SELECT CONVERT(date,rcvdte,103), count(*) as nb
FROM p_rqt p WITH (NOLOCK)
INNER JOIN p_cpy WITH (NOLOCK) ON p_cpy.CpyInCde = p.OrigCpyInCde
WHERE
CpyTypInCde IN (27, 31)
AND p.RqtNatInCde IN (74, 75, 76)
AND HeadRqtInCde = 0
AND ((RcvDte < DATEADD(day, 1, '20170901') AND RqtEndDte IS NULL) OR (RcvDte < DATEADD(day, 1, '20170901') AND RqtEndDte > DATEADD(day, 1, '20170901')))
group by CONVERT(date,rcvdte,103)
order by CONVERT(date,rcvdte,103)
I tried inner join subqueries, Sum and other stuff
but all I can manage to do is to have the number of records added per day
and I want something like this :
date: NB:
01/01/2017 1950
02/01/2017 1954 (+4 items)
03/01/2017 1945 (-9 items)
Thank you
Use LAG:
WITH cte AS (
SELECT
CONVERT(date, rcvdte, 103) AS date,
COUNT(*) AS nb
FROM p_rqt p WITH (NOLOCK)
INNER JOIN p_cpy WITH (NOLOCK)
ON p_cpy.CpyInCde = p.OrigCpyInCde
WHERE
CpyTypInCde IN (27, 31) AND
p.RqtNatInCde IN (74, 75, 76) AND
HeadRqtInCde = 0 AND
((RcvDte < DATEADD(day, 1, '20170901') AND RqtEndDte IS NULL) OR (RcvDte < DATEADD(day, 1, '20170901') AND RqtEndDte > DATEADD(day, 1, '20170901')))
GROUP BY CONVERT(date, rcvdte, 103)
ORDER BY CONVERT(date, rcvdte, 103)
)
SELECT
t1.date,
(SELECT SUM(t2.nb) FROM cte t2 WHERE t2.date <= t1.date) AS nb,
CASE WHEN t1.nb - LAG(t1.nb, 1, t1.nb) OVER (ORDER BY t1.date) > 0
THEN '(+' + (t1.nb - LAG(t1.nb, 1, t1.nb) OVER (ORDER BY t1.date)) + ' items)'
ELSE '(' + (t1.nb - LAG(t1.nb, 1, t1.nb) OVER (ORDER BY t1.date)) + ' items)'
END AS difference
FROM cte t1
ORDER BY t1.date;
So i found a solution but it is really slow,
i still post the answer anyway
DECLARE #Tb TABLE ( Colonne1 Datetime, Colonne2 INT )
DECLARE #Debut Datetime = '01/09/2017'
WHILE #Debut < '13/09/2017'
BEGIN
DECLARE #Compteur int = (
SELECT
COUNT(1) NB
FROM p_rqt WITH (NOLOCK)
INNER JOIN p_cpy WITH (NOLOCK) ON p_cpy.CpyInCde = p_rqt.OrigCpyInCde
WHERE
CpyTypInCde IN (27, 31)
AND p_rqt.RqtNatInCde IN (74, 75, 76)
AND HeadRqtInCde = 0
AND p_rqt.OrigCpyInCde LIKE '%'
AND (
(RcvDte < #Debut AND RqtEndDte IS NULL)
OR
(RcvDte < #Debut AND RqtEndDte > #Debut)
)
)
INSERT INTO #Tb (Colonne1, Colonne2) VALUES (#Debut, #Compteur)
SET #Debut = DATEADD(day, 1, #Debut)
IF #Debut > '13/09/2017'
BREAK
ELSE
CONTINUE
END
SELECT * FROM #Tb
I am using CTE for union two columns in sql.
If I am executing these two queries it is working fine .
But I want to make union of these two for more simpler O/P.
I am getting compile time error :
Incorrect syntax near the keyword 'DECLARE'.
can anyone tell me hoe to achieve union with cte
DECLARE #Inward DATETIME
SET #Inward = DATEADD(mm, -6, CURRENT_TIMESTAMP);
WITH cte AS
(
SELECT 0 AS TheMonth
UNION ALL
SELECT TheMonth + 1
FROM cte
WHERE TheMonth < 5
)
SELECT
cte.TheMonth,
isnull(sum(qty),0) as inward
FROM
cte
LEFT OUTER JOIN RS_GIN_Master as g
ON accept_date >= DATEADD(MM, cte.TheMonth, #Inward) AND accept_date < DATEADD(MM, cte.TheMonth + 1, #Inward)
UNION all
DECLARE #Outward DATETIME
SET #Outward = DATEADD(mm, -6, CURRENT_TIMESTAMP);
WITH cte AS
(
SELECT 0 AS TheMonthO
UNION ALL
SELECT TheMonthO + 1
FROM cte
WHERE TheMonthO < 5
)
SELECT isnull(sum(quantity),0) as outward
FROM
cte
LEFT OUTER JOIN
RS_Sell_Order_Master as s
ON del_date >= DATEADD(MM, cte.TheMonthO, #Outward) AND del_date < DATEADD(MM, cte.TheMonthO + 1, #Outward) and isDelivered = 1
left outer join RS_Sell_Order_Mapping as sm on sm.sell_order_no = s.sell_order_no
Where to begin.
You cannot use declare statements inside of union statements.
Union statements must return the same number of columns.
Common table expressions should only be defined at the beginning of your statement.
Your Sum aggregate needs a group by to return each month.
Perhaps you're looking for something like this:
DECLARE #Inward DATETIME
DECLARE #Outward DATETIME
SET #Inward = DATEADD(mm, -6, CURRENT_TIMESTAMP);
SET #Outward = DATEADD(mm, -6, CURRENT_TIMESTAMP);
WITH cte AS
(
SELECT 0 AS TheMonth
UNION ALL
SELECT TheMonth + 1
FROM cte
WHERE TheMonth < 5
)
SELECT
cte.TheMonth,
isnull(sum(qty),0) as inward,
null as outward
FROM
cte
LEFT OUTER JOIN RS_GIN_Master as g
ON accept_date >= DATEADD(MM, cte.TheMonth, #Inward)
AND accept_date < DATEADD(MM, cte.TheMonth + 1, #Inward)
GROUP BY cte.TheMonth
UNION all
SELECT
cte.TheMonth,
null as inward,
isnull(sum(quantity),0) as outward
FROM
cte
LEFT OUTER JOIN RS_Sell_Order_Master as s
ON del_date >= DATEADD(MM, cte.TheMonthO, #Outward)
AND del_date < DATEADD(MM, cte.TheMonthO + 1, #Outward) and isDelivered = 1
left outer join RS_Sell_Order_Mapping as sm on
sm.sell_order_no = s.sell_order_no
GROUP BY cte.TheMonth
Ha! I'm looked it today because i had the same question. You must declare the first CTE with the "WITH" Keyword and every CTE you need, just separate it with a comma.
EDIT from sgeedes Query above
DECLARE #Inward DATETIME
DECLARE #Outward DATETIME
SET #Inward = DATEADD(mm, -6, CURRENT_TIMESTAMP);
SET #Outward = DATEADD(mm, -6, CURRENT_TIMESTAMP);
WITH cte AS
(
SELECT 0 AS TheMonth
UNION ALL
SELECT TheMonth + 1
FROM cte
WHERE TheMonth < 5
)
SELECT TheMonth,sum(Inward) as InWard, sum(OutWard) as OutWard
FROM
(
SELECT
cte.TheMonth,
isnull(sum(qty),0) as inward,
0 as outward
FROM
cte
LEFT OUTER JOIN RS_GIN_Master as g
ON accept_date >= DATEADD(MM, cte.TheMonth, #Inward)
AND accept_date < DATEADD(MM, cte.TheMonth + 1, #Inward)
GROUP BY cte.TheMonth
UNION all
SELECT
cte.TheMonth,
0 as inward,
isnull(sum(quantity),0) as outward
FROM
cte
LEFT OUTER JOIN RS_Sell_Order_Master as s
ON del_date >= DATEADD(MM, cte.TheMonthO, #Outward)
AND del_date < DATEADD(MM, cte.TheMonthO + 1, #Outward) and isDelivered = 1
left outer join RS_Sell_Order_Mapping as sm on
sm.sell_order_no = s.sell_order_no
GROUP BY cte.TheMonth
)Z
I'm a bit stumped how I might go about this.
I have a very basic query, that currently returns sales for each product, by year and month.
It is grouping by year/month, and summing up the quantity.
This returns one row for each product/year/month combo where there was a sale.
If there was no sale for a month, then there is no data.
I'd like my query to return one row of data for each product for each year/month in my date range, regardless of whether there was actually an order.
If there was no order, then I can return 0 for that product/year/month.
Below is my example query.
Declare #DateFrom datetime, #DateTo Datetime
Set #DateFrom = '2012-01-01'
set #DateTo = '2013-12-31'
select
Convert(CHAR(4),order_header.oh_datetime,120) + '/' + Convert(CHAR(2),order_header.oh_datetime,110) As YearMonth,
variant_detail.vad_variant_code,
sum(order_line_item.oli_qty_required) as 'TotalQty'
From
variant_Detail
join order_line_item on order_line_item.oli_vad_id = variant_detail.vad_id
join order_header on order_header.oh_id = order_line_item.oli_oh_id
Where
(order_header.oh_datetime between #DateFrom and #DateTo)
Group By
Convert(CHAR(4),order_header.oh_datetime,120) + '/' + Convert(CHAR(2),order_header.oh_datetime,110),
variant_detail.vad_variant_code
You can generate this by using CTE.
You will find information on this article :
http://blog.lysender.com/2010/11/sql-server-generating-date-range-with-cte/
Especially this piece of code :
WITH CTE AS
(
SELECT #start_date AS cte_start_date
UNION ALL
SELECT DATEADD(MONTH, 1, cte_start_date)
FROM CTE
WHERE DATEADD(MONTH, 1, cte_start_date) <= #end_date
)
SELECT *
FROM CTE
Thank your for your suggestions.
I managed to get this working using another method.
Declare #DateFrom datetime, #DateTo Datetime
Set #DateFrom = '2012-01-01'
set #DateTo = '2013-12-31'
select
YearMonthTbl.YearMonth,
orders.vad_variant_code,
orders.qty
From
(SELECT Convert(CHAR(4),DATEADD(MONTH, x.number, #DateFrom),120) + '/' + Convert(CHAR(2),DATEADD(MONTH, x.number, #DateFrom),110) As YearMonth
FROM master.dbo.spt_values x
WHERE x.type = 'P'
AND x.number <= DATEDIFF(MONTH, #DateFrom, #DateTo)) YearMonthTbl
left join
(select variant_Detail.vad_variant_code,
sum(order_line_item.oli_qty_required) as 'Qty',
Convert(CHAR(4),order_header.oh_datetime,120) + '/' + Convert(CHAR(2),order_header.oh_datetime,110) As 'YearMonth'
FROM order_line_item
join variant_detail on variant_detail.vad_id = order_line_item.oli_vad_id
join order_header on order_header.oh_id = order_line_item.oli_oh_id
Where
(order_header.oh_datetime between #DateFrom and #DateTo)
GROUP BY variant_Detail.vad_variant_code,
Convert(CHAR(4),order_header.oh_datetime,120) + '/' + Convert(CHAR(2),order_header.oh_datetime,110)
) as Orders on Orders.YearMonth = YearMonthTbl.YearMonth
This is what I put together. It will certainly need some debugging, but I think that this will lead you in the right direction. I broke up the queries into different parts in order to attempt to make it easier to read. Hope this helps.
DECLARE #dateFrom DATETIME, #dateTo DATETIME
SELECT #dateFrom = MIN(oh_datetime) FROM order_header
SELECT #dateTo = MAX(oh_datetime) FROM order_header
;WITH
y AS
(
SELECT YEAR(#dateFrom) AS [Year]
UNION ALL
SELECT [Year] + 1
FROM y
WHERE
[Year] < YEAR (GETDATE())
),
m AS
(
SELECT 1 AS [Month]
UNION ALL
SELECT [Month] + 1
FROM m
WHERE
[Month] < 12
),
dates AS
(
SELECT
CAST(y.[Year] AS nvarchar(4)) + N'/' + RIGHT(N'00' + CAST(m.[Month] AS nvarchar(2)), 2) AS YearMonth
FROM
y CROSS JOIN m
),
qty AS
(
SELECT
YEAR(oh.oh_datetime) + N'/' + MONTH(oh.oh_datetime) AS YearMonth,
v.vad_variant_code,
oli.oli_qty_required AS Qty
FROM
variant_Detail AS v
INNER JOIN order_line_item AS oli ON oil.oli_vad_id = v.vad_id
INNER JOIN order_header AS oh ON oh.oh_id = oli.oli_oh_id
)
SELECT
d.YearMonth,
qty.vad_variant_code,
SUM(qty.Qty) AS TotalQty
FROM
dates AS d LEFT OUTER JOIN qty
ON d.YearMonth = qty.YearMonth
GROUP BY
d.YearMonth,
qty.vad_variant_code
Here is another twist, if you find all months of a year
;WITH DateYear AS (
SELECT 0 AS num
UNION ALL
SELECT num + 1 FROM DateYear
WHERE num < 11
)
Select FirstDateOfTheMonth, DATENAME(mm,FirstDateOfTheMonth), num from
(SELECT CONVERT(DATE,DATEADD(MONTH,num,'2017')) AS FirstDateOfTheMonth, num from DateYear)
cte
and the result will be
Another twist:
Declare #dateFrom datetime ='2019-03-21', #dateTo datetime ='2019-12-31'
;WITH CTE AS
(
SELECT #dateFrom AS cte_start_date
UNION ALL
SELECT DATEADD(MONTH, 1, cte_start_date)
FROM CTE
WHERE ( DATEADD(MONTH, 1, cte_start_date) <= EOMONTH( #dateTo) )
--or ( DATENAME(MONTH, cte_start_date) =DATENAME(MONTH, #dateTo) and DATENAME(year, cte_start_date) =DATENAME(year, #dateTo) ) )
)
SELECT *
FROM CTE
This below is work for sqlserver 2012 and above to get the last day of the month :-
Select EOMONTH('2020-02-15')
I have a query below which draws the quantity of sales committed by men for the current as well as previous month, I like to find out if it is efficient to do it this way because it looks repetitive and if I were to get the report for a year then the query will be extremely long. Please advice if I can in any ways improve on this query, I am looking at performance improvements or even code reduction. Thanks.
Declare #CurrentMonth varchar(20)
Declare #PreviousMonth varchar(20)
Set #CurrentMonth =
(
select count(*) from transact t
join card c
on (t.cardno = c.cardno)
join member m
on (c.Memberid = m.id)
where mode ='1'
and voidby is null
and gender='M'
and month(transactdate) = month(getdate())
)
Set #PreviousMonth =
(
select count(*) from transact t
join card c
on (t.cardno = c.cardno)
join member m
on (c.Memberid = m.id)
where mode='1'
and voidby is null
and gender='M'
and month(transactdate) = month(dateadd(month, -1, (getdate())))
)
select #currentMonth, #PreviousMonth
Please check result with your previous version. Quite important it can use index on transactdate if such exists.
declare #CurMonth int
declare #PrevMonth int
select #PrevMonth = sum(
case
when transactdate < select dateadd(mm, datediff(mm, 0, getdate()), 0)
then 1 else 0 end
),
#CurMonth = sum(
case
when transactdate > select dateadd(mm, datediff(mm, 0, getdate()), 0)
then 1 else 0 end
)
from transact t
join card c on t.cardno = c.cardno
join member m on c.Memberid = m.id
where mode ='1'
and voidby is null
and gender='M'
and transactdate >= dateadd(mm, datediff(mm, 0, getdate()) - 1, 0)
and transactdate < dateadd(mm, datediff(mm, 0, getdate()) + 1, 0)