I have a Fiscal Calendar table in SQL Server 2012 Express. I would like to be able to pull the first date of each week and display them in a row starting from next week. Meaning, I want the first row to display 9/2/2013, then 9/9/2013, 9/16/2013, etc. Here is how I have the table constructed along with some data.
[dbo].[FiscalCalendar](
[FiscalDate] [datetime] NULL,
[FiscalWeekNum] [smallint] NULL,
[FiscalMonthNum] [smallint] NULL,
[FiscalMonthName] [varchar](9) NULL,
[FiscalYear] [smallint] NULL
FiscalDate FiscalWeekNum FiscalMonthNum FiscalMonthName FiscalYear
2013-09-02 00:00:00.000 36 9 September 2013
2013-09-03 00:00:00.000 36 9 September 2013
2013-09-04 00:00:00.000 36 9 September 2013
2013-09-05 00:00:00.000 36 9 September 2013
2013-09-06 00:00:00.000 36 9 September 2013
2013-09-07 00:00:00.000 36 9 September 2013
2013-09-08 00:00:00.000 36 9 September 2013
2013-09-09 00:00:00.000 37 9 September 2013
2013-09-10 00:00:00.000 37 9 September 2013
2013-09-11 00:00:00.000 37 9 September 2013
2013-09-12 00:00:00.000 37 9 September 2013
2013-09-13 00:00:00.000 37 9 September 2013
2013-09-14 00:00:00.000 37 9 September 2013
2013-09-15 00:00:00.000 37 9 September 2013
SET DATEFIRST 7;
;WITH x AS
(
SELECT <cols>, rn = ROW_NUMBER() OVER
(PARTITION BY FiscalWeekNum ORDER BY FiscalDate)
FROM dbo.FiscalCalendar
WHERE FiscalDate >= CONVERT(DATE, GETDATE())
AND DATEPART(WEEKDAY, FiscalDate) = 2
)
SELECT <cols> FROM x WHERE rn = 1;
Related
I have 5 mandatory courses which is [ Python, Java, Kotlin, SQL, React ]. And I have different tables
Table name : dbo.course
course_id
course_name
mandatory
category_id
1
python
yes
20
2
java
yes
20
3
kotlin
yes
20
4
sql
yes
20
5
react
yes
20
6
c++
no
21
7
git
no
22
8
vb.net
no
23
table name : Table name : dbo.category which is linked to dbo.course
category_id
category_name
20
Dev
21
Bridge
22
PM
23
Bas
Table name : dbo.attendance (p = present , a = absent)
participant_id
status
course_id
log_in_date
log_out_date
1
p
1
july 2021
july 2021
1
p
2
july 2021
july 2021
1
p
3
july 2021
july 2021
1
p
4
july 2021
july 2021
1
p
5
july 2021
july 2021
2
p
1
july 2021
july 2021
3
a
6
null
null
4
a
8
null
null
5
p
1
july 2021
july 2021
5
p
2
july 2021
july 2021
5
p
3
july 2021
july 2021
5
p
4
july 2021
july 2021
5
p
5
july 2021
july 2021
if the participant finished all the mandatory courses then it will count as 1 and if not, it will not count unless he/she finish the training. I want the output something like this : Assume that there is 5 participant that finished the training in August 2021 and 10 participant in September 2021
select date,count(participant), count(*)
date
participant
count
july 2021
2
2
august 2021
5
7
september 2021
10
17
I have a graph where I have sales value for Jan, Feb, Mar state wise. I want to mark a flag in a column, if sales exceeds previous month for March month say.
Sales Sales Sales
City1 Person 1 12 29 10
Person 2 14 15 19
Person 3 23 24 11
City2 Person 4 22 28 30
Person 5 14 15 10
Person 6 23 24 2
Jan Feb Mar and so on
So basically expected output would be:
Sales Sales Sales Flag
City1 Person 1 12 29 10 Down arrow
Person 2 14 15 19 Up arrow
Person 3 23 24 11 Down Arrow
City2 Person 4 22 28 30 Up arrow
Person 5 14 15 10 Down arrow
Person 6 23 24 2 Down arrow
Jan Feb Mar and so on
Can anyone tell how to do this in a graph visualisation?
The values of sales are sum (Sales) for Jan , Feb and Mar respectively for Cities corresponding to each person
Based on this answer by Burak Arslan
SELECT date_trunc('month', txn_date) AS txn_month, sum(amount) as monthly_sum
FROM yourtable
GROUP BY txn_month
Is there a way to get months that have no results to show in the query?
So let's say I have :
id transDate Product Qty
1234 04/12/2019 ABCD 2
1245 04/05/2019 ABCD 1
1231 02/07/2019 ABCD 6
I also need to the the third Month returns with a 0 value
MonthYear totalQty
02/2019 6
03/2019 0
04/2019 3
Thanks,
---- UPDATE ---
Here is the final query that that gets last 24 months from the current date. with year and month ready for any charts.
Thanks to #a_horse_with_no_name
SELECT
--ONLY USE THE NEXT LINE IF YOU NEED TO HAVE THE ID IN YOUR RESULT
CASE WHEN t."ItemId" IS NULL THEN 10607 ELSE t."ItemId" END AS "ItemId",
TO_CHAR(y."transactionDate", 'yyyy-mm-dd') AS txn_month,
TO_CHAR(y."transactionDate", 'yyyy') AS "Year",
TO_CHAR(y."transactionDate", 'Mon') AS "Month",
-coalesce(SUM(t."transactionQty"),0) AS "TotalSold"
FROM generate_series(
TO_CHAR(CURRENT_DATE - INTERVAL '24 month', 'yyyy-mm-01')::date ,
TO_CHAR(CURRENT_DATE, 'yyyy-mm-01')::date,
INTERVAL '1 month') as y("transactionDate")
LEFT JOIN "ItemTransactions" AS t
ON date_trunc('month', t."transactionDate") = y."transactionDate"
AND t."ItemTransactionTypeId" = 1
AND t."ItemId" = 10607
GROUP BY txn_month, "Year", "Month", t."ItemId"
ORDER BY txn_month ASC;
EXEMPLE OUTPUT
ItemId txn_month Year Month TotalSold
10607 2018-03-01 2018 Mar 2
10607 2018-04-01 2018 Apr 0
10607 2018-05-01 2018 May 8
10607 2018-06-01 2018 Jun 12
10607 2018-07-01 2018 Jul 6
10607 2018-08-01 2018 Aug 4
10607 2018-09-01 2018 Sep 6
10607 2018-10-01 2018 Oct 8
10607 2018-11-01 2018 Nov 4
10607 2018-12-01 2018 Dec 0
10607 2019-01-01 2019 Jan 2
10607 2019-02-01 2019 Feb 3
10607 2019-03-01 2019 Mar 4
10607 2019-04-01 2019 Apr 1
10607 2019-05-01 2019 May 4
10607 2019-06-01 2019 Jun 3
10607 2019-07-01 2019 Jul 5
10607 2019-08-01 2019 Aug 6
10607 2019-09-01 2019 Sep 6
10607 2019-10-01 2019 Oct 6
10607 2019-11-01 2019 Nov 3
10607 2019-12-01 2019 Dec 0
10607 2020-01-01 2020 Jan 4
10607 2020-02-01 2020 Feb 2
10607 2020-03-01 2020 Mar 0
Left join to a list of months:
SELECT t.txn_month,
coalesce(sum(yt.amount),0) as monthly_sum
FROM generate_series(date '2019-02-01', date '2019-04-01', interval '1 month') as t(txn_month)
left join yourtable yt on date_trunc('month', yt.transdate) = t.txn_month
GROUP BY t.txn_month
Online example
In your actual query you need to move the conditions from the WHERE clause to the JOIN condition. Putting them into the WHERE clause turns the outer join back into an inner join:
SELECT t."ItemId",
y."transactionDate" AS txn_month,
-coalesce(SUM(t."transactionQty"),0) AS "TotalSold"
FROM generate_series(date '2018-01-01', date '2020-04-01', INTERVAL '1 month') as y("transactionDate")
LEFT JOIN "ItemTransactions" AS t
ON date_trunc('month', t."transactionDate") = y."transactionDate"
AND t."ItemTransactionTypeId" = 1
AND t."ItemId" = 10606
-- this WHERE clause isn't really needed because of the date values provided to generate_series()
WHERE AND y."transactionDate" >= NOW() - INTERVAL '2 year'
GROUP BY txn_month, t."ItemId"
ORDER BY txn_month DESC;
I have a table which contains some records ordered by date.
And I want to get start and end dates for each subsequent group (grouped by some criteria e.g.position).
Example:
create table tbl (id int, date timestamp without time zone,
position int);
insert into tbl values
( 1 , '2013-12-01', 1),
( 2 , '2013-12-02', 2),
( 3 , '2013-12-03', 2),
( 4 , '2013-12-04', 2),
( 5 , '2013-12-05', 3),
( 6 , '2013-12-06', 3),
( 7 , '2013-12-07', 2),
( 8 , '2013-12-08', 2)
Of course if I simply group by position I will get wrong result as positions could be the same for different groups:
SELECT POSITION, min(date) MIN, max(date) MAX
FROM tbl GROUP BY POSITION
I will get:
POSITION MIN MAX
1 December, 01 2013 00:00:00+0000 December, 01 2013 00:00:00+0000
3 December, 05 2013 00:00:00+0000 December, 06 2013 00:00:00+0000
2 December, 02 2013 00:00:00+0000 December, 08 2013 00:00:00+0000
But I want:
POSITION MIN MAX
1 December, 01 2013 00:00:00+0000 December, 01 2013 00:00:00+0000
2 December, 02 2013 00:00:00+0000 December, 04 2013 00:00:00+0000
3 December, 05 2013 00:00:00+0000 December, 06 2013 00:00:00+0000
2 December, 07 2013 00:00:00+0000 December, 08 2013 00:00:00+0000
I found a solution for MySql which uses variables and I could port it but I believe PostgreSQL can do it in some smarter way using its advanced features like window functions.
I'm using PostgreSQL 9.2
There is probably more elegant solution but try this:
WITH tmp_tbl AS (
SELECT *,
CASE WHEN lag(position,1) OVER(ORDER BY id)=position
THEN position
ELSE ROW_NUMBER() OVER(ORDER BY id)
END AS grouping_col
FROM tbl
)
, tmp_tbl2 AS(
SELECT position,date,
CASE WHEN lag(position,1)OVER(ORDER BY id)=position
THEN lag(grouping_col,1) OVER(ORDER BY id)
ELSE ROW_NUMBER() OVER(ORDER BY id)
END AS grouping_col
FROM tmp_tbl
)
SELECT POSITION, min(date) MIN, max(date) MAX
FROM tmp_tbl2 GROUP BY grouping_col,position
There are some complete answers on Stackoverflow for that, so I'll not repeat them in detail, but the principle of it is to group the records according to the difference between:
The row number when ordered by the date (via a window function)
The difference between the dates and a static date of reference.
So you have a series such as:
rownum datediff diff
1 1 0 ^
2 2 0 | first group
3 3 0 v
4 5 1 ^
5 6 1 | second group
6 7 1 v
7 9 2 ^
8 10 2 v third group
I have a year table like this. Every year has 12 values (Fixed)
declare #t table (FiscalYear int,[Month] varchar(25))
insert into #t values
(2011,'Jan'),(2011,'Feb'),(2011,'Mar'),(2011,'Apr'),
(2011,'May'),(2011,'Jun'),(2011,'Jul'),(2011,'Aug'),
(2011,'Sep'),(2011,'Oct'),(2011,'Nov'),(2011,'Dec'),
(2012,'Jan'),(2012,'Feb'),(2012,'Mar'),(2012,'Apr'),
(2012,'May'),(2012,'Jun'),(2012,'Jul'),(2012,'Aug'),
(2012,'Sep'),(2012,'Oct'),(2012,'Nov'),(2012,'Dec'),
(2013,'Jan'),(2013,'Feb'),(2013,'Mar'),(2013,'Apr'),
(2013,'May'),(2013,'Jun'),(2013,'Jul'),(2013,'Aug'),
(2013,'Sep'),(2013,'Oct'),(2013,'Nov'),(2013,'Dec')
I want to output as
FYear Month Qt Qtp
2011 Jan 1 1
2011 Feb 1 2
2011 Mar 1 3
2011 Apr 2 1
2011 May 2 2
2011 Jun 2 3
2011 Jul 3 1
2011 Aug 3 2
2011 Sep 3 3
2011 Oct 4 1
2011 Nov 4 2
2011 Dec 4 3
2012 Jan 1 1
2012 Feb 1 2
2012 Mar 1 3
2012 Apr 2 1
2012 May 2 2
2012 Jun 2 3
2012 Jul 3 1
2012 Aug 3 2
2012 Sep 3 3
2012 Oct 4 1
2012 Nov 4 2
2012 Dec 4 3
2013 Jan 1 1
2013 Feb 1 2
2013 Mar 1 3
2013 Apr 2 1
2013 May 2 2
2013 Jun 2 3
2013 Jul 3 1
2013 Aug 3 2
2013 Sep 3 3
2013 Oct 4 1
2013 Nov 4 2
2013 Dec 4 3
How can i do that in SQLServer2008R2. I have tried using DenseRank, RowNuber, Partitioned but all in vain.
Tru using Ntile:
--select * from #t
SELECT * ,
ROW_NUMBER() OVER ( PARTITION BY FYear, Qt ORDER BY FYear ) Qtp
from
(SELECT FYear,[Month],
NTILE(4) OVER ( PARTITION BY FYear ORDER BY FYear ) AS Qt
FROM #t) PERIOD
ORDER BY FYear ,Qt ,ROW_NUMBER() OVER ( PARTITION BY FYear, Qt ORDER BY FYear)
I propose dynamically populating a table with date values from Dec 2013 going down to the year that you like (you can alter the #COUNT_Y Variable to add more years).
SQL has some interesting datetime functions like DATEPART which can tell you which quarter a month is in etc.
** Answer changed due to question change **
DECLARE #DATES TABLE
(
xDATE DATETIME
)
DECLARE #STARTDATE DATETIME = '12-31-2013'
DECLARE #COUNT_X INT = 0
DECLARE #COUNT_X_MAX INT = 11
DECLARE #COUNT_Y INT = 0
DECLARE #COUNT_Y_MAX INT = 2
WHILE (#COUNT_Y <= #COUNT_Y_MAX)
BEGIN
SET #COUNT_X = 0
WHILE (#COUNT_X <= #COUNT_X_MAX)
BEGIN
INSERT INTO #DATES
SELECT DATEADD(MONTH, -#COUNT_X, DATEADD(YEAR,-#COUNT_Y, #STARTDATE))
SET #COUNT_X = #COUNT_X + 1
END
SET #COUNT_Y = #COUNT_Y + 1
END
SELECT * FROM
(SELECT
DATEPART(YEAR, D.xDATE) AS [YEAR],
DATEPART(MONTH, D.xDATE) AS [MONTH],
DATENAME(MONTH, D.xDATE) AS [MONTH_NAME],
DATEPART(QUARTER, D.xDATE) AS [QUARTER],
DATEPART(MONTH, D.xDATE) - (3 * (DATEPART(QUARTER, D.xDATE) - 1)) AS [QTP]
FROM #DATES D) t
ORDER BY T.YEAR, T.MONTH