SQL database get all dates between two dates in sql [duplicate] - sql-server

I created a chart that will plot data to show value for present data on specific date
with this SQL
select substring(TRAN_DATE, 1, 4) MONTH, substring(TRAN_DATE, 5, 2) DATE, count(*) AMOUNT from TA1606 group by TRAN_DATE
this is field structure
TRAN_DATE char(6)
with this create command
CREATE TABLE [dbo].[TA16](
[TRAN_DATE] [char](6) NULL,
[TERM] [char](16) NULL,
)
this my result is
MONTH DATE AMOUNT
1606 03 44
but this is just only one row and one day
i need to get all day of month in example is 06 June it will query all day in the month then mapping data to date as my result above shown
this is my expected result
MONTH DATE AMOUNT
1606 1 0
1606 2 0
1606 3 44
1606 4 0
1606 5 0
1606 6 0
1606 7 0
1606 8 0
1606 9 0
1606 10 0
1606 11 0
1606 12 0
1606 13 0
1606 14 0
1606 15 0
1606 16 0
1606 17 0
1606 18 0
1606 19 0
1606 20 0
1606 21 0
1606 22 0
1606 23 0
1606 24 0
1606 25 0
1606 26 0
1606 27 0
1606 28 0
1606 29 0
1606 30 0

Basically the idea is to use a left join between a calendar table and your data table.
There are many ways to create a calendar table, I like to use a tally table for that.
So the First thing you should do, if you don't already have a tally table, is to create one.
If you are asking your self what is a tally table and why do you need it, read this article by Jeff Moden
SELECT TOP 1001 IDENTITY(int,0,1) AS Number
INTO Tally
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Tally ADD CONSTRAINT PK_Tally PRIMARY KEY CLUSTERED (Number)
Now, Create and populate sample data (Please save us this step in your next question)
DECLARE #TA16 TABLE (
[TRAN_DATE] [char](6) NULL,
[TERM] [char](16) NULL
)
INSERT INTO #TA16 VALUES ('160603', '44')
Then, Use a CTE to create a calendar for the relevant year (or month, what ever is best for you),
And since you are using char to keep the date, we need another cte to convert that char value to proper date.
;With Calendar as
(
SELECT DATEADD(DAY, Number, '2016-01-01') TheDate
FROM Tally
WHERE Number < 367 -- Most years are 365 days, but leap years are 366, so it will cover leap years as well
), TA16WithActualDate AS
(
SELECT [TRAN_DATE],
[TERM],
CONVERT(date, LEFT([TRAN_DATE], 2) +'.'+ SUBSTRING ([TRAN_DATE], 3, 2) +'.'+ RIGHT([TRAN_DATE], 2), 2) As ActualDate
FROM #TA16
)
Now, select from Calendar left joined to the TA16WithActualDate cte and format the output as you wish:
SELECT REPLACE(CONVERT(char(5), TheDate, 2), '.', '') As [Month],
RIGHT(CONVERT(char(8), TheDate, 2), 2) As [Date],
ISNULL([TERM], 0) As Amount
FROM Calendar
LEFT JOIN TA16WithActualDate ON TheDate = TRAN_DATE
WHERE MONTH(TheDate) = 6
Results:
Month Date Amount
--- ---- ------
1606 01 0
1606 02 0
1606 03 44
1606 04 0
1606 05 0
1606 06 0
1606 07 0
1606 08 0
1606 09 0
1606 10 0
1606 11 0
1606 12 0
1606 13 0
1606 14 0
1606 15 0
1606 16 0
1606 17 0
1606 18 0
1606 19 0
1606 20 0
1606 21 0
1606 22 0
1606 23 0
1606 24 0
1606 25 0
1606 26 0
1606 27 0
1606 28 0
1606 29 0
1606 30 0

Try like this,
SELECT TOP 1 substring(TRAN_DATE, 1, 4) MONTH
,substring(TRAN_DATE, 5, 2) DATE
,count(*) AMOUNT
FROM TA1606
GROUP BY TRAN_DATE
ORDER BY 3 DESC
This query would probably give result like this.
MONTH DATE AMOUNT
1606 3 44

Related

Displaying full years worth of data when part way through

I am attempting to display a full years worth of data when only part way through the year and it has been requested to display these future months of the year as 0.
I do not want to add these further months manually post query as when we enter March, March will start displaying data.
My query:
SELECT
FORMAT(a.CreatedDateTime, 'MMM') AS 'month',
SUM(b.NewContactCount) AS 'new_total',
SUM(b.TotalContactCount) AS 'all_total'
FROM database.dbo.ImportBatch a
LEFT JOIN ImportBatch_File b ON a.id = b.BatchID
WHERE a.CreatedDateTime >= CAST(YEAR(GETDATE()) AS VARCHAR) + '/01/01'
GROUP BY FORMAT(a.CreatedDateTime, 'MMM'), MONTH(a.CreatedDateTime)
ORDER BY MONTH(a.CreatedDateTime)
My results:
month new_total all_total
1 Jan 337 1000
2 Feb 146 497
My desired outcome:
month new_total all_total
1 Jan 337 1000
2 Feb 146 497
3 Mar 0 0
4 Apr 0 0
5 May 0 0
6 Jun 0 0
7 Jul 0 0
8 Aug 0 0
9 Sep 0 0
10 Oct 0 0
11 Nov 0 0
12 Dec 0 0

Grouping items and setting a flag

I have a table structured as follows:
order_yr acct_id indv_id age
2019 323 01 38
2019 323 02 37
2019 323 03 16
2019 323 04 5
2019 325 01 38
2019 326 01 64
2019 326 02 63
What I need to do is by order_yr and acct_id add a flag if the order_yr and acct_id has someone age <=17.
The result would be like this:
order_yr acct_id indv_id age child_flg
2019 323 01 38 1
2019 323 02 37 1
2019 323 03 16 1
2019 323 04 5 1
2019 325 01 38 0
2019 326 01 64 0
2019 326 02 63 0
I know I have to partition by order_yr and acct_id, but not sure how to get the result in one inline script.
Any help would be appreciated.
BTW this is an individual level extract with a number of other columns associated with each indv.
I've not gotten very far - I have this:
,ROW_NUMBER() OVER(PARTITION BY order_yr, acct_id ORDER BY (CASE WHEN age <=17 THEN 'Y' ELSE 'N' END) desc) AS CHILD_flg
You have some options here. One is using a subquery to find out if a row exists that belongs to a group and meets your condition:
select *
, case
when exists (select *
from #data sub
where sub.order_yr = d.order_yr
and sub.acct_id = d.acct_id
and sub.age <= 17)
then 1
else 0
end as flag
from #data d
You can also go with a window function like you planned:
select *
, max(case when age <= 17 then 1 else 0 end) over (partition by order_yr, acct_id) as flag
from #data d
Working demo on dbfiddle

Subtract depletion And Limit for SUM

First I'm using AdventureWork2019 as a reference
I have a query where I'm joining 5 Tables
USE [AdventureWorks2019]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Alter PROCEDURE dbo.TestLocation
#UseDate DateTime
AS
BEGIN
SET NOCOUNT ON;
SELECT prodID
,SUM(PurchQty) AS TotalPurchase
,SUM(SalesQty) AS TotalSell
,StartDate
from (
SELECT DISTINCT WO.ProductID AS prodID
, StartDate
,WO.OrderQty AS PurchQty
,SOD.OrderQty AS SalesQty
FROM Sales.SalesOrderDetail SOD
LEFT JOIN Production.WorkOrderRouting WOR ON WOR.ProductID = SOD.ProductID
--LEFT JOIN Production.Location PL ON PL.LocationID = WOR.LocationID
--The above Join is the one for the locationID and it's working Fine
LEFT JOIN Production.WorkOrder WO ON WO.ProductID = SOD.ProductID
FULL OUTER JOIN Purchasing.PurchaseOrderDetail POD ON POD.ProductID = SOD.ProductID
WHERE StartDate = #UseDate
-- AND PL.LocationID >= 10
) Test3
Group by prodID,StartDate
order by prodID ASC, StartDate
END
GO
EXEC TestLocation '2011-07-02 00:00:00.000'
Output(sample):
prodID TotalPurc TotalSell StartDate
717 8 36 2011-07-02 00:00:00.000
730 9 47 2011-07-02 00:00:00.000
744 2 3 2011-07-02 00:00:00.000
747 12 21 2011-07-02 00:00:00.000
749 5 15 2011-07-02 00:00:00.000
761 16 138 2011-07-02 00:00:00.000
775 26 91 2011-07-02 00:00:00.000
777 12 78 2011-07-02 00:00:00.000
802 6 21 2011-07-02 00:00:00.000
804 40 60 2011-07-02 00:00:00.000
806 16 138 2011-07-02 00:00:00.000
807 24 23 2011-07-02 00:00:00.000
810 21 28 2011-07-02 00:00:00.000
811 6 21 2011-07-02 00:00:00.000
813 8 37 2011-07-02 00:00:00.000
817 21 28 2011-07-02 00:00:00.000
And another Table For LocationID (as a warehouse)
SELECT LocationID,CostRate,Availability
FROM Production.Location
WHERE LocationID >= 10
order by CostRate ASC
LocationID CostRate Availability
50 12.25 120.00
60 12.25 120.00
30 14.50 120.00
40 15.75 120.00
45 18.00 80.00
10 22.50 96.00
20 25.00 108.00
What I want to do is to take each LoactionId and ProdID and take TotalPurc to the location and decrement the quantity in the Availability column, each TotalSell will increment the Availability column. The max Availability quantity is 130.
If all locations have no Available quantity that is the Available is 0 for all locations then it will stop.
the above will work with the date specified as you can check the query and run it if you have
AdventureWork2019
simple output to check how I want the data to be:
prodID TotalPurc TotalSell StartDate
717 8 36 2011-07-02 00:00:00.000
730 9 47 2011-07-02 00:00:00.000
744 2 3 2011-07-02 00:00:00.000
747 12 21 2011-07-02 00:00:00.000
749 5 15 2011-07-02 00:00:00.000
LocationID CostRate Availability
50 12.25 120.00
60 12.25 120.00
30 14.50 120.00
40 15.75 120.00
45 18.00 80.00
10 22.50 96.00
20 25.00 108.00
Output :
prodID TotalPurc TotalSell StartDate LocationID Availability Remaining
717 8 36 2011-07-02 00:00:00.000 50 130 18
717 8 36 2011-07-02 00:00:00.000 60 130 8
717 8 36 2011-07-02 00:00:00.000 30 128 0
--what happened above is that I took the (120-8) = 112 then 112+36 = 148 we only can use 130 then the remaining is 18 then we took the next `LocationID` with the least Cost (120+18 = 138 we can use 130 so we took the 8) and used it in the next `LocationID`
730 9 47 2011-07-02 00:00:00.000 30 130 36
730 9 47 2011-07-02 00:00:00.000 40 130 26
730 9 47 2011-07-02 00:00:00.000 45 106 0
744 2 3 2011-07-02 00:00:00.000 45 107 0
747 12 21 2011-07-02 00:00:00.000 45 116 0
749 5 15 2011-07-02 00:00:00.000 45 126 0
--the above is the same as the first 3 rows we subtract and add to the availability
The other condition is that if all locations reached 0 or 130 then stop
How can I do that in SQL Server? I tried using CTE but didn't work well with me and tried the cursor which I think is the best for this kind of thing but didn't achieve anything.
Thank you in advance
Edit :
ALTER FUNCTION GetStockMovment
(
-- Add the parameters for the function here
#ForDate Datetime
)
RETURNS #Sums TABLE (
RemoveQTY Numeric(24, 7),
ADDQTY Numeric(24, 7)
)
AS
BEGIN
Declare #WoSum Numeric(24, 7),
#SODSUM Numeric(24, 7),
#WORSum Numeric(24, 7),
#PODSum Numeric(24, 7)
select #SODSUM = SUM(SOD.OrderQty) from Sales.SalesOrderDetail SOD
INNER JOIN Sales.SalesOrderHeader SOH ON SOD.SalesOrderID = SOH.SalesOrderID
where SOH.OrderDate = #ForDate
select #WoSum = sum(orderQty) from Production.WorkOrder
where StartDate = #ForDate
select #PODSum = sum(POD.OrderQty) from Purchasing.PurchaseOrderDetail POD
INNER JOIN Purchasing.PurchaseOrderHeader POH ON POD.PurchaseOrderID = POH.PurchaseOrderID
where POH.OrderDate = #ForDate
select #WoSum = sum(WO.OrderQty) from Production.WorkOrder WO
where WO.DueDate = #ForDate
INSERT INTO #Sums (RemoveQTY,ADDQTY)
SELECT isnull(#SODSUM,0) + isnull(#WORSum,0) , isnull(#PODSum,0) + isnull(#WoSum,0)
RETURN;
END;
GO
select * from dbo.GetStockMovment ('2014-05-26 00:00:00.000')
Output:
RemoveQTY ADDQTY
189.0000000 5334.0000000
You should use LAG or LEAD function.
https://learn.microsoft.com/en-us/sql/t-sql/functions/lead-transact-sql?view=sql-server-ver15
https://learn.microsoft.com/en-us/sql/t-sql/functions/lag-transact-sql?view=sql-server-ver15

Using SQL (or T-SQL), How to get the length of Time a value was 0 or 1 each hour from a table that records the date and time a value was set?

I have a table with the following data:
StartTime Value
----------------------------------------------
2016-12-20 08:09:00 1
2016-12-20 09:53:00 0
2016-12-20 11:10:21 1
2016-12-20 11:30:00 1
2016-12-20 12:20:30 0
.... ....
.... ....
2016-12-20 23:44:10 1
2016-12-21 00:33:00 0
2016-12-21 01:05:05 0
So, what I'm trying to do is find how long a value was 0 or 1 during each hour, where the hours are from 00:00:00 - 01:00:00, then from 01:00:00 - 02:00:00 ... 23:00:00 - 00:00:00.
what I want to achieve looks like this:
HourStart Period Value Was 0 Period Value Was 1
--------------------------------------------------------------------------
2016-12-20 00:00:00 50 min 10 min
2016-12-20 01:00:00 30 30
2016-12-20 02:00:00 32 28
2016-12-20 03:00:00 60 00
2016-12-20 04:00:00 21 39
.... .... ....
.... .... ....
2016-12-20 21:00:00 30 30
2016-12-20 22:00:00 20 40
2016-12-20 23:00:00 10 50
2016-12-21 00:00:00 01 59
2016-12-21 01:00:00 30 30
.... ....
By the way, I'm using Microsoft Transact-SQL.
Thanks.
Here is one way to do this:
First, create and populate sample table (Please save us this step in your future questions)
DECLARE #T as TABLE
(
startTime datetime,
value int
)
INSERT INTO #T VALUES
('2016-12-20 08:09:00', 1),
('2016-12-20 09:53:00', 0),
('2016-12-20 11:10:21', 1),
('2016-12-20 11:30:00', 1),
('2016-12-20 12:20:30', 0),
('2016-12-20 23:44:10', 1),
('2016-12-21 00:33:00', 0),
('2016-12-21 01:05:05', 0)
Then, use a couple of common table expressions - one to get rid of the minutes and seconds of the start time, and the second one to get the start time of the previous row:
;WITH cte1 as
(
SELECT StartTime,
value,
DATEADD(SECOND, -DATEPART(SECOND, startTime), DATEADD(MINUTE, -DATEPART(MINUTE, startTime), startTime)) As startHour
FROM #T
), cte2 as
(
SELECT StartTime,
value,
StartHour,
DATEDIFF(MINUTE, ISNULL(LAG(startTime) OVER(Partition by startHour ORDER BY startTime), startHour), startTime) As minutes
FROM cte1
)
Then, select from the second cte:
SELECT startHour,
value,
CASE WHEN value = 1 THEN
minutes
ELSE
60 - minutes
END as minutes_1,
CASE WHEN value = 0 THEN
minutes
ELSE
60 - minutes
END as minutes_0
FROM cte2
Results:
startHour value minutes_1 minutes_0
20.12.2016 08:00:00 1 9 51
20.12.2016 09:00:00 0 7 53
20.12.2016 11:00:00 1 10 50
20.12.2016 11:00:00 1 20 40
20.12.2016 12:00:00 0 40 20
20.12.2016 23:00:00 1 44 16
21.12.2016 00:00:00 0 27 33
21.12.2016 01:00:00 0 55 5

joining two tables [duplicate]

This question already has an answer here:
Closed 12 years ago.
Possible Duplicate:
How to join two tables
table 1
Date StartingAum
07/01/2010 120
08/01/2010 220
09/01/2010 320
table 2
Date DepContr withdra
01/01/2010 60 15
02/01/2010 70 25
03/01/2010 80 15
04/01/2010 30 89
05/01/2010 40 15
06/01/2010 25 85
07/01/2010 16 17
08/01/2010 19 21
09/01/2010 68 79
the output should be
Date StartingAum DepContr withdra
01/01/2010 0 60 15
02/01/2010 0 70 25
03/01/2010 0 80 15
04/01/2010 0 30 89
05/01/2010 0 40 15
06/01/2010 0 25 85
07/01/2010 120 16 17
08/01/2010 220 19 21
09/01/2010 320 68 79
i need the output exactly similar to that
DECLARE #Table1 table ([date] datetime, StartingAum int)
DECLARE #Table2 table ([date] datetime, DepContr int, withdra int)
INSERT #Table1 VALUES ('07/01/2010', 120)
INSERT #Table1 VALUES ('08/01/2010', 220)
INSERT #Table1 VALUES ('09/01/2010', 320)
INSERT #Table2 VALUES ('01/01/2010', 60 , 15)
INSERT #Table2 VALUES ('02/01/2010', 70 , 25)
INSERT #Table2 VALUES ('03/01/2010', 80 , 15)
INSERT #Table2 VALUES ('04/01/2010', 30 , 89)
INSERT #Table2 VALUES ('05/01/2010', 40 , 15)
INSERT #Table2 VALUES ('06/01/2010', 25 , 85)
INSERT #Table2 VALUES ('07/01/2010', 16 , 17)
INSERT #Table2 VALUES ('08/01/2010', 19 , 21)
INSERT #Table2 VALUES ('09/01/2010', 68 , 79)
SELECT
t2.[Date]
,ISNULL(t1.StartingAum, 0) AS StartingAum
,t2.DepContr
,t2.withdra
FROM #Table2 t2
LEFT JOIN #Table1 t1 ON t2.[Date] = t1.[Date]
ORDER BY t2.[Date]
OUTPUT:
Date StartingAum DepContr withdra
----------------------- ----------- ----------- -----------
2010-01-01 00:00:00.000 0 60 15
2010-02-01 00:00:00.000 0 70 25
2010-03-01 00:00:00.000 0 80 15
2010-04-01 00:00:00.000 0 30 89
2010-05-01 00:00:00.000 0 40 15
2010-06-01 00:00:00.000 0 25 85
2010-07-01 00:00:00.000 120 16 17
2010-08-01 00:00:00.000 220 19 21
2010-09-01 00:00:00.000 320 68 79
I think you should have a look at this page: http://www.w3schools.com/sql/sql_union.asp
That might be helpful?

Resources