I have the following query. I need an output which would look like this
ea_month case ea_year zone_id
January 0 2013 4001
February 0 2013 4002
March 1 2013 4001
January 0 2014 4001
February 0 2014 4001
March 1 2014 4001
February 0 2014 4002
March 1 2014 4002
SELECT ea_month,CASE WHEN ea_month = (SELECT to_char(now(), 'Month')) THEN 1 ELSE 0 END,ea_year,zone_id FROM staging_ea.stg_circle_zone_billedamount_rollup
In my table I have my values for ea_month in the form of January, February, March.
After running the above query, the result-set that I am getting is something like this:
ea_month case ea_year zone_id
January 0 2013 4001
February 0 2013 4002
March 0 2013 4001
January 0 2014 4001
February 0 2014 4001
March 0 2014 4001
February 0 2014 4002
March 0 2014 4002
Can anyone suggest me where am I going wrong? Its for a PostgreSQL query.
This is caused by the to_char() function padding the month name with spaces. This can either be fixed by applying a trim() on the result or using the FM modifier in the format mask:
SELECT ea_month,
CASE
WHEN ea_month = to_char(current_date, 'FMMonth') THEN 1
ELSE 0
END,
ea_year,
zone_id
FROM staging_ea.stg_circle_zone_billedamount_rollup;
See the manual for details: http://www.postgresql.org/docs/current/static/functions-formatting.html#FUNCTIONS-FORMATTING-DATETIMEMOD-TABLE
Related
Probaly a simple solution to this, but it elludes me.
I have a SQL-Server (2017) table like this:
rn
wk
day
subj
1
202225
mon
subj1
2
202225
mon
subj2
3
202225
mon
subj3
1
202225
tue
subj4
2
202225
tue
subj5
1
202225
wed
subj6
2
202225
wed
subj7
1
202226
mon
subj8
2
202226
mon
subj9
1
202226
tue
subj10
1
202226
wed
subj11
2
202226
wed
subj12
3
202226
wed
subj13
I want to transpose this table to this using T-sql:
wk
mon
tue
wed
202225
subj1
subj4
subj6
202225
subj2
subj5
subj7
202225
subj3
NULL
NULL
202226
subj8
subj10
subj11
202226
subj9
NULL
subj12
202226
NULL
NULL
subj13
I tried using PIVOT, but the aggregate MAX function only gives me one record per week for the wk column. What is the correct / best SQL solution?
This is what I tried:
select * from (select wk, subj, day from mytable ) d
pivot (max(subj) for day in (mon, tue, wed, thu, fri, sat, sun)) piv;
This is just a simple pivot, or (what I and many others prefer) conditional aggregation:
SELECT wk,
MAX(CASE day WHEN 'mon' THEN subj END) AS mon,
MAX(CASE day WHEN 'tue' THEN subj END) AS tue,
MAX(CASE day WHEN 'wed' THEN subj END) AS wed
FROM (VALUES(1,202225,'mon','subj1'),
(2,202225,'mon','subj2'),
(3,202225,'mon','subj3'),
(1,202225,'tue','subj4'),
(2,202225,'tue','subj5'),
(1,202225,'wed','subj6'),
(2,202225,'wed','subj7'),
(1,202226,'mon','subj8'),
(2,202226,'mon','subj9'),
(1,202226,'tue','subj10'),
(1,202226,'wed','subj11'),
(2,202226,'wed','subj12'),
(3,202226,'wed','subj13'))V(rn,wk,day,subj)
GROUP BY rn,
wk
ORDER BY wk,
rn;
db<>fiddle
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
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 run this report Mon-Fri for the previous day's data and I am trying to figure out how to hard code TO_CHAR(TRUNC(SYSDATE-3) if today is
Monday (day the report is run) or use TO_CHAR(TRUNC(SYSDATE-1) for any other workday (mon - fri). I am assuming that this will require an IF, THEN, ELSE statement but am unsure of how to include that properly into my query.
SELECT
RRA.LAST_MODIFICATION_DATE AS "LAST MODIFICATION DATE",
TO_CHAR(TRUNC(SYSDATE-1),'DD-MON-RR') AS "DATA_DATE"
FROM PHOENIX.R_REFERRAL_ACTIVITY RRA
Where 1=1
AND RRA.LAST_MODIFICATION_DATE
BETWEEN TO_CHAR(TRUNC(SYSDATE-1),'DD-MON-RR') AND TO_CHAR(TRUNC(SYSDATE),'DD-MON-RR')
Aha; OK then, it seems that you'd need to use CASE along with TO_CHAR function which will tell you which day is "today". Have a look, see if it helps.
TEST is just a simple calendar, several days in this February. I'm removing Saturdays and Sundays (as you said you're interested in mon - fri only).
SQL> with test as
2 (select trunc(sysdate, 'mm') + level - 1 c_date,
3 to_char(trunc(sysdate, 'mm') + level - 1, 'dy') c_day
4 from dual
5 connect by level < 20
6 )
7 select
8 c_date todays_date,
9 c_day,
10 --
11 c_date - case when c_day = 'mon' then 3
12 else 1
13 end previous_work_date,
14 --
15 to_char(c_date - case when c_day = 'mon' then 3
16 else 1
17 end, 'dy') previous_work_day
18 from test
19 where c_day not in ('sat', 'sun')
20 order by 1;
TODAYS_DAT C_D PREVIOUS_W PRE
---------- --- ---------- ---
01.02.2018 thu 31.01.2018 wed
02.02.2018 fri 01.02.2018 thu
05.02.2018 mon 02.02.2018 fri
06.02.2018 tue 05.02.2018 mon
07.02.2018 wed 06.02.2018 tue
08.02.2018 thu 07.02.2018 wed
09.02.2018 fri 08.02.2018 thu
12.02.2018 mon 09.02.2018 fri
13.02.2018 tue 12.02.2018 mon
14.02.2018 wed 13.02.2018 tue
15.02.2018 thu 14.02.2018 wed
16.02.2018 fri 15.02.2018 thu
19.02.2018 mon 16.02.2018 fri
13 rows selected.
SQL>
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