can anyone tell me the sql query(MySQL) that will result following output from the table .
You're after a PIVOT TABLE QUERY - although it's often better to perform the basic aggregation in (My)SQL and then handle problems of display at the application level (e.g. with a bit of PHP).
A standard query might look as follows, although MySQL supports shorthand deviations from this standard...
SELECT DATE_FORMAT(date,'%M') month
, COALESCE(SUM(CASE WHEN status = 'Rahul' THEN value END),0) Rahul
, COALESCE(SUM(CASE WHEN status = 'Vijay' THEN value END),0) Vijay
, COALESCE(SUM(CASE WHEN status = 'Loki' THEN value END),0) Loki
FROM my_table
GROUP
BY MONTH(date);
WITH w AS (
SELECT 10 AS value, 'Rahul' AS status, TO_DATE('20/01/2013', 'DD/MM/YYYY') AS date_time FROM dual
UNION ALL
SELECT 15, 'Vijay', TO_DATE('28/02/2013', 'DD/MM/YYYY') FROM dual
UNION ALL
SELECT 20, 'Loki', TO_DATE('03/02/2013', 'DD/MM/YYYY') FROM dual
UNION ALL
SELECT 25, 'Kiran', TO_DATE('05/01/2013', 'DD/MM/YYYY') FROM dual
UNION ALL
SELECT 5, 'Rahul', TO_DATE('02/01/2013', 'DD/MM/YYYY') FROM dual
UNION ALL
SELECT 15, 'Vijay', TO_DATE('10/01/2013', 'DD/MM/YYYY') FROM dual
UNION ALL
SELECT 08, 'Loki', TO_DATE('01/01/2013', 'DD/MM/YYYY') FROM dual
)
SELECT TO_CHAR(date_time, 'Mon') AS m
, SUM(CASE status WHEN 'Rahul' THEN value ELSE 0 END) AS Rahul
, SUM(CASE status WHEN 'Vijay' THEN value ELSE 0 END) AS Vijay
, SUM(CASE status WHEN 'Loki' THEN value ELSE 0 END) AS Loki
, SUM(CASE status WHEN 'Kiran' THEN value ELSE 0 END) AS Kiran
, SUM(value) AS Total
FROM w
GROUP BY TO_CHAR(date_time, 'Mon')
ORDER BY TO_DATE(TO_CHAR(date_time, 'Mon'), 'Mon')
;
Related
How do you rewrite this code correctly in Snowflake?
select account_code, date,
sum(box_revenue_recognition_amount) as box_revenue_recognition_amount
, sum(case when box_flg = 1 then box_sku_quantity end) as box_sku_quantity
, sum(box_revenue_recognition_refund_amount) as box_revenue_recognition_refund_amount
, sum(box_discount_amount) as box_discount_amount
, sum(box_shipping_amount) as box_shipping_amount
, sum(box_cogs) as box_cogs
, max(invoice_number) as invoice_number
, max(order_number) as order_number
, min(box_refund_date) as box_refund_date
, first (case when order_season_rank = 1 then box_type end) as box_type
, first (case when order_season_rank = 1 then box_order_season end) as box_order_season
, first (case when order_season_rank = 1 then box_product_name end) as box_product_name
, first (case when order_season_rank = 1 then box_coupon_code end) as box_coupon_code
, first (case when order_season_rank = 1 then revenue_recognition_reason end) as revenue_recognition_reason
from dedupe_sub_user_day
group by account_code, date
I have tried to apply window rule has explained in first_value Snowflake documentation to no avail with the SQLCompilation Error: ... is not a valid group by expression
select account_code, date,
first_value(case when order_season_rank = 1 then box_type end) over (order by box_type ) as box_type
first_value(case when order_season_rank = 1 then box_order_season end) over (order by box_order_season ) as box_order_season,
first_value(case when order_season_rank = 1 then box_product_name end) over (order by box_product_name ) as box_product_name,
first_value(case when order_season_rank = 1 then box_coupon_code end) over (order by box_coupon_code ) as box_coupon_code,
first_value(case when order_season_rank = 1 then revenue_recognition_reason end) over (order by revenue_recognition_reason ) as revenue_recognition_reason
, sum(box_revenue_recognition_amount) as box_revenue_recognition_amount
, sum(case when box_flg = 1 then box_sku_quantity end) as box_sku_quantity
, sum(box_revenue_recognition_refund_amount) as box_revenue_recognition_refund_amount
, sum(box_discount_amount) as box_discount_amount
, sum(box_shipping_amount) as box_shipping_amount
, sum(box_cogs) as box_cogs
, max(invoice_number) as invoice_number
, max(order_number) as order_number
, min(box_refund_date) as box_refund_date
from dedupe_sub_user_day
group by 1,2
First_value is not an aggregate function. But an window function, thus you get an error when you use it in relation to a GROUP BY. If you want to use it with a group up put an ANY_VALUE around it.
here is some data I will use below in a CTE:
with data(id, seq, val) as (
select * from values
(1, 1, 10),
(1, 2, 11),
(1, 3, 12),
(1, 4, 13),
(2, 1, 20),
(2, 2, 21),
(2, 3, 22)
)
So to show FIRST_VALUE is a window function we can just use it
select *
,first_value(val)over(partition by id order by seq) as first_val
from data
ID
SEQ
VAL
FIRST_VAL
1
1
10
10
1
2
11
10
1
3
12
10
1
4
13
10
2
1
20
20
2
2
21
20
2
3
22
20
So if we GROUP BY id, to avoid an error we have to wrap the FIRST_VALUE by an aggregate value, as given the are all equal, ANY_VALUE is a good pick, and it seems it needs to be in another layer of SQL:
select id
,count(*) as count
,any_value(first_val) as first_val
from (
select *
,first_value(val)over(partition by id order by seq) as first_val
from data
)
group by 1
order by 1;
ID |COUNT |FIRST_VAL
1 |4 |10
2 |3 |20
now MAX can be fun to use where used in relation to ROW_NUMBER() to pick the best value:
select id
,count(*) as count
,max(first_val) as first_val
from (
select *
,row_number() over (partition by id order by seq) as rn
,iff(rn=1, val, null) as first_val
from data
)
group by 1
order by 1;
but this is almost more complex than the ANY_VALUE solution, but I feel the performance would be better, but if they have the same magnitude of performance, I would always choose readable to you and your team, over a smaller performance difference.
With the way you've written your case statement, it leads me to believe that there is only one row with order_season_rank = 1 when grouping by account_code and date.
If that is true, then you can use several of Snowflake's aggregate functions and you will get what you want. Rather than trying to get the first value, you could use min, max, any_value, mode (or really any aggregate function that will ignore nulls) to return the only non-null value in the aggregation.
first() this link suggests first is only supported by MS ACCESS however you've tagged the question with MYSQL, Snowflake. Could you confirm the DBMS's you are using?
by moving the first_value() function outside the aggregation it seems to work fine
I have a table named incident_summary that structure and data as following:
month,system_id,s_count
202104,1,50
202104,2,6
202105,1,14
202105,2,4
202106,1,1
202106,2,1
I would like to generate the following statistic:
s_count_on_202106,s_count_before_202106
2,74
where
s_count_on_202106 is sum of s_count value on 202106
s_count_before_202106 is sum of s_count value before 202106
I have tried the following SQL:
select
sum(case when month<202106 then s_count else 0 end)
sum(case when month=202106 then s_count else 0 end)
from incident_summary
group by month
However, it does not work, would you help to me to solve the problem?
Try the following Query.
May be it helps you.
SELECT
t1.s_count_on_202106,
t2.s_count_before_202106
FROM
(
SELECT
sum(s_count) AS s_count_on_202106
FROM
incident_summary
WHERE
month = 202106
) AS t1,
(
SELECT
sum(s_count) AS s_count_before_202106
FROM
incident_summary
WHERE
month < 202106
) AS t2
Sum again on your result set.
SELECT SUM(s_count_before_202106)s_count_before_202106, SUM(s_count_on_202106)s_count_on_202106
FROM
(
select
sum(case when month<202106 then s_count else 0 end)s_count_before_202106 ,
sum(case when month=202106 then s_count else 0 end)s_count_on_202106
from incident_summary
group by month
)T;
Locked. There are disputes about this question’s content being resolved at this time. It is not currently accepting new answers or interactions.
I am new to SQL and would like to know how to approach writing a query for this question.
Lets say we have these fields:
date_created date_unsubscribed subscriberid
How to write a SQL query that lists, by month, how many people subscribed to the list, unsubscribed from the list, and how many net subscribers there were (new subscribers minus unsubscribers).
All in a single query...
Here's one option using conditional aggregation and union all:
select month(dt),
count(case when subscribe = 1 then 1 end) subscribecount,
count(case when subscribe = -1 then 1 end) unsubscribecountt,
sum(subscribe) overallcount
from (
select date_created as dt, 1 as subscribe
from yourtable
union all
select date_unsubscribed, -1
from yourtable
where date_unsubscribed is not null
) t
group by month(dt)
The subquery creates a list of dates with a flag for subscribe or unsubscribe. Then you can use count with case to determine the appropriate number of subscribers/unsubscribers.
SQL Fiddle Demo
You could write a sum(case) (a sum with conditions) to aggregate - assuming the date_created column is never null. For instance:
ORACLE:
SELECT
TO_CHAR(DATE_CREATED,'MM-YYYY') CREATE_MONTH
,SUM(CASE WHEN date_unsubscribed is not null then 1 else 0 end) unsubscribed
,SUM(CASE WHEN date_unsubscribed is null then 1 else 0 end) subscribed
,COUNT(SUBSCRIBER_ID)
FROM
--YOURTABLENAME
--WHERE
--WHATEVER OTHER CONDITIONS YOU HAVE APPLY
GROUP BY TO_CHAR(DATE_CREATED,'MM-YYYY')
MYSQL:
SELECT
DATE_FORMAT(DATE_CREATED,'%m-%Y') CREATE_MONTH
,SUM(CASE WHEN date_unsubscribed is not null then 1 else 0 end) unsubscribed
,SUM(CASE WHEN date_unsubscribed is null then 1 else 0 end) subscribed
,COUNT(SUBSCRIBER_ID)
FROM
--YOURTABLENAME
--WHERE
--WHATEVER OTHER CONDITIONS YOU HAVE APPLY
GROUP BY DATE_FORMAT(DATE_CREATED,'%m-%Y')
Oracle solution
Here is a query using the PIVOT operator, which was created exactly for this kind of work, and ROLLUP to get the net number. This is just for illustration; I assume the year is a user or application input (bind variable :year, set to 2015 for the output), and I show the summary for January through June.
with
test_data ( date_created, date_unsubscribed, subscriber_id ) as (
select date '2015-05-10', null , 330053448 from dual union all
select date '2015-04-28', null , 330053457 from dual union all
select date '2015-05-10', null , 330053466 from dual union all
select date '2015-04-28', null , 220053475 from dual union all
select date '2015-04-28', date '2015-05-10', 330053484 from dual
),
prep ( type, val, mth ) as (
select 'Subscribed' , 1, extract(month from date_created) from test_data
where extract(year from date_created) = :year
union all
select 'Unsubscribed', -1, extract(month from date_unsubscribed) from test_data
where extract(year from date_unsubscribed) = :year
)
select nvl(type, 'Net Subscr') as description,
nvl(sum(jan), 0) as jan, nvl(sum(feb), 0) as feb, nvl(sum(mar), 0) as mar,
nvl(sum(apr), 0) as apr, nvl(sum(may), 0) as may, nvl(sum(jun), 0) as jun
from prep
pivot (
sum(val)
for mth in (1 as jan, 2 as feb, 3 as mar, 4 as apr, 5 as may, 6 as jun)
)
group by rollup(type)
order by case type when 'Subscribed' then 1 when 'Unsubscribed' then 2 else 3 end
;
DESCRIPTION JAN FEB MAR APR MAY JUN
------------ ---------- ---------- ---------- ---------- ---------- ----------
Subscribed 0 0 0 3 2 0
Unsubscribed 0 0 0 0 -1 0
Net Subscr 0 0 0 3 1 0
3 rows selected.
I retrieve two sum of value:
SUM (CASE WHEN CAUSALI.AVAILABLECAUSA_1 LIKE ('%CAUSE-1%') THEN (mtscrap) ELSE 0 END ) as Cause1
and
SUM (CASE WHEN CAUSALI.AVAILABLECAUSA_1 LIKE ('%CAUSE-2%') THEN (mtscrap) ELSE 0 END ) as Cause2
I would like to set another SUM statement without %CAUSE-*, and that have WHERE clause independent from the principal WHERE. I had innested this subquery:
(CASE WHEN day BETWEEN '2014-01-09' AND '2014-06-13' THEN SUM(MTSCRAP) ELSE 0 END) AS XXXXXX
but I have wrong data. My global query is:
SELECT
SezioneID
, Desc_Prod
, sample.products.VETTURA AS VetturaID
, truncate((SUM(mtscrap_1) / SUM(MtProdotti_1)) * 100, 2) AS Scrap_1
, truncate((SUM(mtscrap_2) / SUM(MtProdotti_2)) * 100, 2) AS Scrap_2
, mtscrap_1
, MtProdotti_1
, mtscrap_2
, MtProdotti_2
FROM flB.flB_prod AS PROD
JOIN SAMPLE.PRODUCTS
ON (sample.products.SKU = PROD.SEZIONEID)
AND (sample.products.LINEA = 'FLB')
JOIN (
SELECT
IDSEZIONE
, IDTURNO
, ID_PROG
, SUM(CASE
WHEN AVAILABLECAUSA_1 LIKE ('%CHANGE-1%') THEN mtscrap ELSE 0
END) AS mtscrap_1
, SUM(CASE
WHEN AVAILABLECAUSA_1 LIKE ('%CHANGE-1%') THEN MtProdotti ELSE 0
END) AS MtProdotti_1
, SUM(CASE
WHEN AVAILABLECAUSA_1 LIKE ('%CHANGE-2%') THEN mtscrap ELSE 0
END) AS mtscrap_2
, SUM(CASE
WHEN AVAILABLECAUSA_1 LIKE ('%CHANGE-2%') THEN MtProdotti ELSE 0
END) AS MtProdotti_2
, MtProdotti
FROM FLB.flB_causali
WHERE DATASTARTPRG BETWEEN '2014-06-09' AND '2014-06-13'
GROUP BY
IDSEZIONE
IDTURNO
, ID_PROG
) AS CAUSALI
ON (PROD.SEZIONEID = CAUSALI.IDSEZIONE)
AND PROD.TURNO = CAUSALI.IDTURNO
AND PROD.ID_PROG = CAUSALI.ID_PROG
WHERE giorno BETWEEN '2014-06-09' AND '2014-06-13'
GROUP BY
SezioneID
I need this view:
I have done my best to put a table or alias beside EVERY field reference. At this point I really do not know what else I can do for you. I don't think any more words will help.
these 2 simple items will help:
1. sample data
2. expected result
Because you did not use table aliases on all fields in the very original query the following is a complete guess, but using the presence of DISTINCT in that original query was a clue for "too many rows" that indicated the need for grouping prior to the overall query. So, here's my first guess:
SELECT
PROD.SezioneID
, PROD.Desc_Prod
, sample.products.VETTURA AS VetturaID
, truncate((SUM(CAUSALI.mtscrap_1) / SUM(CAUSALI.MtProdotti_1)) * 100, 2) AS Scrap_1
, truncate((SUM(CAUSALI.mtscrap_2) / SUM(CAUSALI.MtProdotti_2)) * 100, 2) AS Scrap_2
, CAUSALI.mtscrap_1
, CAUSALI.MtProdotti_1
, CAUSALI.mtscrap_2
, CAUSALI.MtProdotti_2
FROM flB.flB_prod AS PROD
JOIN SAMPLE.PRODUCTS
ON (sample.products.SKU = PROD.SEZIONEID)
AND (sample.products.LINEA = 'FLB')
JOIN (
SELECT
flB_causali.IDSEZIONE
, flB_causali.IDTURNO
, flB_causali.ID_PROG
, SUM(CASE
WHEN flB_causali.AVAILABLECAUSA_1 LIKE ('%CHANGE-1%') THEN flB_causali.mtscrap ELSE 0
END) AS mtscrap_1
, SUM(CASE
WHEN flB_causali.AVAILABLECAUSA_1 LIKE ('%CHANGE-1%') THEN flB_causali.MtProdotti ELSE 0
END) AS MtProdotti_1
, SUM(CASE
WHEN flB_causali.AVAILABLECAUSA_1 LIKE ('%CHANGE-2%') THEN flB_causali.mtscrap ELSE 0
END) AS mtscrap_2
, SUM(CASE
WHEN flB_causali.AVAILABLECAUSA_1 LIKE ('%CHANGE-2%') THEN flB_causali.MtProdotti ELSE 0
END) AS MtProdotti_2
, flB_causali.MtProdotti
FROM FLB.flB_causali
WHERE flB_causali.DATASTARTPRG BETWEEN '2014-06-09' AND '2014-06-13'
GROUP BY
flB_causali.IDSEZIONE
flB_causali.IDTURNO
, flB_causali.ID_PROG
) AS CAUSALI
ON (PROD.SEZIONEID = CAUSALI.IDSEZIONE)
AND PROD.TURNO = CAUSALI.IDTURNO
AND PROD.ID_PROG = CAUSALI.ID_PROG
WHERE PROD.giorno BETWEEN '2014-06-09' AND '2014-06-13'
GROUP BY
PROD.SezioneID
;
Are you looking for this expression?
SUM(CASE WHEN day BETWEEN '2014-01-09' AND '2014-06-13' THEN MTSCRAP ELSE 0 END) AS XXXXXX
The CASE goes inside the SUM() for conditional aggregation.
I am using sql server 2008
I have table in my database is like this:
And I want output like this:
As it is shown in my table I have DateField which has smalldatetime datatype and along with fruits and vegi fields. I want output like which shows data month-wise.. month comparison should be performed based on DateField of my table.
You can use something like:
select [Month] = month(DateField)
, [MonthName] = left(datename(mm, DateField), 3)
, TotalAmountApple = sum(case when fruits = 'Apple' then 1 else 0 end)
, TotalAmountOnion = sum(case when vegi = 'Onion' then 1 else 0 end)
from produce
group by month(DateField)
, left(datename(mm, DateField), 3)
order by [Month]
Full test details (no SQL Fiddle as it's experiencing issues):
create table produce
(
id int
, fruits varchar(10)
, vegi varchar(10)
, DateField smalldatetime
)
insert into produce
select 1, 'Apple', 'Chilly', '01-jan-2013'
insert into produce
select 1, 'Mango', 'Onion', '15-jan-2013'
insert into produce
select 1, 'Mango', 'Chilly', '20-jan-2013'
insert into produce
select 1, 'Apple', 'Chilly', '01-Feb-2013'
insert into produce
select 1, 'Mango', 'Onion', '15-Feb-2013'
insert into produce
select 1, 'Apple', 'Onion', '20-Feb-2013'
select [Month] = month(DateField)
, [MonthName] = left(datename(mm, DateField), 3)
, TotalAmountApple = sum(case when fruits = 'Apple' then 1 else 0 end)
, TotalAmountOnion = sum(case when vegi = 'Onion' then 1 else 0 end)
from produce
group by month(DateField)
, left(datename(mm, DateField), 3)
order by [Month]