How do i convert columns into rows for each status - sql

Data is saved in a table is as below.
I need to show data as below.
Please suggest a query

This is how you would do it in SQL Server:
SELECT Name, 'Joined' AS [ACTION], JOIN_DT AS ACTION_DATE
FROM SomeTable
UNION ALL
SELECT Name, 'Started' START_DTTM
FROM SomeTable
UNION ALL
SELECT Name, 'ended', END_DT
FROM SomeTable

Try this:
SELECT Name, Action, Action_Date FROM (
SELECT Name, 'Joined' as Action, JOIN_DT as ACTION_DATE FROM TableA
UNION ALL
SELECT Name, 'Started', START_DT FROM TableA
UNION ALL
SELECT Name, 'Ended', END_DT FROM TableA)
ORDER BY Name;

Related

Get the attributes of the most recent row in BigQuery?

I'm working in BigQuery. I have a table t1 which has address, postcode, price and date fields. I want to group this by address and postcode, an find the price of the most recent row for each address.
How can I do this in BigQuery? I know how to get the address, postcode and most recent date:
SELECT
ADDRESS, POSTCODE, MAX(DATE)
FROM
[mytable]
GROUP BY
ADDRESS,
POSTCODE
But I don't know how to get the price of these rows matching these fields. This is my best guess, which does produce results - will this be correct?
SELECT
t1.address, t1.postcode, t1.date, t2.price
FROM [mytable] t2
JOIN
(SELECT
ADDRESS, POSTCODE, MAX(DATE) AS date
FROM
[mytable]
GROUP BY
ADDRESS,
POSTCODE) t1
ON t1.address=t2.address
AND t1.postcode=t2.postcode
AND t1.date=t2.date
This seems to me like it should work, but some of the similar questions have solutions that are much more complex.
Just use row_number():
SELECT t.*
FROM (SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY ADDRESS, POSTCODE
ORDER BY DATE DESC
) as seqnum
FROM [mytable] t
) t
WHERE seqnum = 1;
This is not an aggregation query. You want to filter the rows to get the most recent value.
Try below for BigQuery Standard SQL
#standardSQL
SELECT row.* FROM (
SELECT ARRAY_AGG(t ORDER BY date DESC LIMIT 1)[OFFSET(0)] AS row
FROM `yourTable` AS t
GROUP BY address, postcode
)
You can play/test it with dummy data as below
#standardSQL
WITH yourTable AS (
SELECT 'address_1' AS address, 'postcode_1' AS postcode, '2017-01-01' AS date, 1 AS price UNION ALL
SELECT 'address_1', 'postcode_1', '2017-01-02', 2 UNION ALL
SELECT 'address_1', 'postcode_1', '2017-01-03', 3 UNION ALL
SELECT 'address_1', 'postcode_1', '2017-01-04', 4 UNION ALL
SELECT 'address_2', 'postcode_2', '2017-01-01', 5 UNION ALL
SELECT 'address_3', 'postcode_1', '2017-01-01', 6 UNION ALL
SELECT 'address_3', 'postcode_1', '2017-01-02', 7 UNION ALL
SELECT 'address_3', 'postcode_1', '2017-01-03', 8
)
SELECT row.* FROM (
SELECT ARRAY_AGG(t ORDER BY date DESC LIMIT 1)[OFFSET(0)] AS row
FROM `yourTable` AS t
GROUP BY address, postcode
)

disply two rows from single row

This is the given table:
I need to get this data without creating temporary table based on the above table:
We can't use temporary table. I need to display the data with sql query only.
Try this
SELECT company name,'No' as value, clicks as data
from table1
union all
SELECT company,'Yes', (clicks - impression)
from table1
order by name,val
You can use UNION ALL to unpivot your table:
SELECT
company,
'No' AS val,
impression AS data
FROM tbl
UNION ALL
SELECT
company,
'Yes' AS val,
clicks - impression AS data
FROM tbl
ORDER BY company, val
You need UNION ALL
SELECT company,'No' val, impression as data from your_table
union all
SELECT company,'Yes' val, clicks-impression as data from your_table
select company as name, 'No' as val, impression as data
from tbl
union
select company as name, 'Yes' as val, clicks - impression as data
from tbl
SELECT COMPANY AS NAME, 'YES' AS VAL, (CLICKS-IMPRESSIONS) AS DATA
FROM ORIGINAL_TABLE
UNION
SELECT COMPANY AS NAME, 'NO' AS VAL, IMPRESSIONS AS DATA
FROM ORIGINAL_TABLE
If you want them sorted: Try this:
SELECT A.NAME, A.VAL, A.DATA FROM
(SELECT COMPANY AS NAME, 'YES' AS VAL, (CLICKS-IMPRESSIONS) AS DATA
FROM OR_TABLE
UNION
SELECT COMPANY AS NAME, 'NO' AS VAL, IMPRESSIONS AS DATA
FROM OR_TABLE) A
ORDER BY A.NAME ASC;

Join based on min

I have two tables.
Table1:
id, date
Table2:
id,date
Both the table contain information about id. Table1 and Table2 can have some extra rows which are not present in another table.
Example:
Table1:
1,15-Jun
2,16-Jun
4,17-Jun
Table2
1,14-Jun
2,17-Jun
3,18-Jun
I need a summarize result which give minimum date for each row.
Expected result:
1,14-Jun
2,16-Jun
3,18-Jun
4,17-Jun
select id, min(date_) from (
select id, date_ from table1
union all
select id, date_ from table12
) group by id;
SELECT id, MIN(date)
FROM (SELECT id, date
FROM Table1
UNION
SELECT id, date
FROM Table2)
GROUP BY id
with a as(select t.i_id,t.dt_date from t
union
select b.i_id,b.dt_date from b)
select a.i_id,min(a.dt_date) from a group by a.i_id order by a.i_id;
You can check this link

How can I filter an SQL table to show only keys with exactly N entries?

Lets say I have a table with a column named KEY.
I want to find all KEYs which are in the table exactly 3 times.
How can I do that?
I managed to get a list of how many entries I have for each KEY, like this:
select count(*) from my_table group by KEY;
but how can I filter it to show only those who have the value 3?
select KEY
from my_table
group by KEY
having count(*) = 3
The having clause filters after grouping (where filters before).
select `key`
from my_table
group by `KEY`
having count(*) = 3;
select KEY
from my_table
group by KEY
having count(1) = 3
Try with Row Number concept
;
WITH Temp_tab AS
( SELECT '1' Key_,'az' Key_Value
UNION SELECT '1' ,'a5'
UNION SELECT '1' ,'a6'
UNION SELECT '2' ,'a1'
UNION SELECT '3' ,'a2'
UNION SELECT '4' ,'a3'
UNION SELECT '1' ,'a4'
UNION SELECT '3' ,'a21'
UNION SELECT '3' ,'a22'),
Tab2 AS
(SELECT *, ROW_NUMBER() over(partition BY key_ ORDER BY key_) count_ FROM Temp_Tab)
SELECT key_
FROM tab2 WHERE count_ = 3
code for your table
;with temp_table
(select *,ROW_NUMBER() over(partition by key_ order by key_) count_ from my_table)
select key_ from temp_table where count_ = 3

ORDER BY CASE does not working?

Hi I have SQL statement in DB2 which is working.
select distinct 'IN' as STATUS,
(select count(*) from table.......)
from table
UNION ALL
select distinct 'OUT',
(select count(*) from table.......)
from table
UNION ALL
select distinct 'FINISHED',
(select count(*) from table.......)
from table
order by status
But if I change the last line to
order by
case STATUS
when 'IN' then 1
when 'OUT' then 2
when 'FINISHED' then 3
end
My query does not work.
Can someone tell me how to solve this?
Thanks
Try wrapping the UNION into a derived table and order on that:
select *
from (
.... here goes your statement ...
) t
order by
case STATUS
when 'IN' then 1
when 'OUT' then 2
when 'FINISHED' then 3
end
you could always add the sort # to the status:
select distinct '1-IN' as STATUS,
(select count(*) from table.......)
from table
UNION ALL
select distinct '2-OUT',
(select count(*) from table.......)
from table
UNION ALL
select distinct '3-FINISHED',
(select count(*) from table.......)
from table
order by status
hello try this should work if i remember correctly
order by
case
when STATUS='IN' then 1
when STATUS='OUT' then 2
when STATUS='FINISHED' then 3
end
you could also name this when finishing
end as field_name