Case on union of multiple unions and issue with alias - sql

I have 2 series of unions which I wish to join by another union. In the first one, I have 3 Selects and in the second one I have 2 different Selects.
Select id, min(value)
from table1 t1
join (Select id, value
Union
Select id, value
Union
Select id, value) as foo
on foo.id=t1.id
Group by id
Select id, max(value)
from table1 t1
join (Select id, value
Union
Select id, value) as bar
on bar.id=t1.id
Group by id
I tried to do a union between these two, but it made things pretty complicated. My biggest issue is with my alias. My second is with the case linked to my value columns, which I wish to name value.
Select (alias).id,
Case
When foo.value= 0 or bar.value=1 THEN 1
Else 0
End as value
from table1 t1
Join (Select id, min(value)
from table1 t1
join (Select id, value
Union
Select id, value
Union
Select id, value) as foo
on foo.id=t1.id
Group by id
UNION
Select id, max(value)
from table1 t1
join (Select id, value
Union
Select id, value) as bar
on bar.id=t1.id
Group by id) as (alias)
on ??.id=??.id
I wrote my case the way I think it should be written, but normally, when there are more than one column with the same name, SQL states it as ambiguous. I am still unsure if I should use UNION or INTERSECT, but I assume either of them would be done the same way. How should I deal with this?

I'm reading this right, you probably want something like this
SELECT ...
FROM ( ... union #1 ) AS u1
JOIN (... union #2 ) AS u2 ON u1.id = u2.id

Related

Getting MAX datetime event from multiple tables, and outputing a simple list of most recent events by ID

I have a table:
and multiple other tables - consider them purchases, in this example:
And would like an output table to show the most recent purchase (NB that there may be multiple instances of a purchase within each table), by id from the main table:
The id can be a customer number, for example.
I've tried using OUTER APPLY on each purchase table, getting the TOP 1 by datetime desc, then getting the max value from the OUTER APPLY tables, but I would not get the table name - eg. Apples, just the datetime.
Another idea was to UNION all of the purchase tables together in a join with the main table (by id), and pick out the top 1 datetime and a table name, but I don't think this would be very efficient for a lot of rows:
SELECT MT.id, MT.gender, MT.age,
b.Name as LastPurchase, b.dt as LastPurchaseDateTime
FROM MainTable MT
LEFT JOIN (
SELECT id, Name, MAX(dt) FROM
(
SELECT id, 'Apples' as Name, ApplesDateTime as dt FROM ApplesTable
UNION
SELECT id, 'Pears' as Name, PearsDateTime as dt FROM PearsTable
UNION
SELECT id, 'Bananas' as Name, BananasDateTime as dt FROM BananasTable
)a
GROUP BY etc
)b
Does anyone have a more sensible idea?
Many thanks in advance.
I would go for a lateral join:
select m.*, x.*
from maintable m
outer apply (
select top (1) x.*
from (
select id, 'apples' as name, applesdatetime as dt from applestable
union all select id, 'pears', pearsdatetime from pearstable
union all select id, 'bananas', bananasdatetime from bananastable
) x
where x.id = m.id
order by dt desc
) x
I would suggest apply:
SELECT MT.id, mt.gender, mt.age, p.*
FROM MainTable MT OUTER APPLY
(SELECT p.name, p.dt
FROM (SELECT id, 'Apples' as Name, ApplesDateTime as dt FROM ApplesTable
UNION ALL
SELECT id, 'Pears' as Name, PearsDateTime as dt FROM PearsTable
UNION ALL
SELECT id, 'Bananas' as Name, BananasDateTime as dt FROM BananasTable
) p
WHERE p.id = mt.id
ORDER BY dt DESC
) p

Select a third column based on two distant rows within the same table

I want to select a third column based on two distant columns within the same table.
I could only think of this:
select tl.thirdcolumn
from table1 t1
WHERE
EXISTS
(
Select distinct tl.firstcolumn , t1.secondcolumn
From t1
)
This:
select distinct tl.thirdcolumn
from table t1
won't work as I don't want the distinct thirdrow. I want the thirdrow to be based on the first two rows being distinct.
I guess its a kind of nested sql statment with a select top 1... idk
CATEGORY NAME Query
---------------------------------------------------
STUDENTS NUMBER_OF_CHAPTERS QueryA
STUDENTS NUMBER_OF_STUDENT_MEMBERS QueryB
STUDENTS NUMBER_OF_STUDENT_MEMBERS QueryB
MEMBERS NUMBER_OF_MEMBERS_WORLDWIDE QueryC
MEMBERS NUMBER_OF_MEMBERS_WORLDWIDE QueryC
Your question is rather hard to follow, but I think you might simply want group by:
select tl.firstcolumn , t1.secondcolumn, max(tl.thirdcolumn)
from table1 t1
group by tl.firstcolumn , t1.secondcolumn;
If you want rows where the pair of values only appears once, then add having count(*) = 1:
select tl.firstcolumn , t1.secondcolumn, max(tl.thirdcolumn)
from table1 t1
group by tl.firstcolumn , t1.secondcolumn
having count(*) = 1;
Query -
SELECT
CATEGORY,NAME,QUERY
FROM
(
WITH TAB AS (
SELECT
'STUDENTS' AS CATEGORY,
'NUMBER_OF_CHAPTERS' AS NAME,
'QUERYA' AS QUERY
FROM
DUAL
UNION ALL
SELECT
'STUDENTS' AS CATEGORY,
'NUMBER_OF_STUDENT_MEMBERS' AS NAME,
'QUERYB' AS QUERY
FROM
DUAL
UNION ALL
SELECT
'STUDENTS' AS CATEGORY,
'NUMBER_OF_STUDENT_MEMBERS' AS NAME,
'QUERYB' AS QUERY
FROM
DUAL
UNION ALL
SELECT
'MEMBERS' AS CATEGORY,
'NUMBER_OF_MEMBERS_WORLDWIDE' AS NAME,
'QUERYC' AS QUERY
FROM
DUAL
UNION ALL
SELECT
'MEMBERS' AS CATEGORY,
'NUMBER_OF_MEMBERS_WORLDWIDE' AS NAME,
'QUERYC' AS QUERY
FROM
DUAL
) SELECT
CATEGORY,
NAME,
QUERY,
COUNT(*) OVER(PARTITION BY
CATEGORY,
NAME
ORDER BY
CATEGORY,
NAME,
QUERY
) AS RNK
FROM
TAB
)
WHERE
RNK = 1;
Output -
"CATEGORY","NAME","QUERY"
"STUDENTS","NUMBER_OF_CHAPTERS","QueryA"

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 to repeat each row twice

I have a requirement for a report and I would like my sql query to repeat each row twice.
Example :
**Table 1**
Id Name
1 Ab
2 Cd
3 Ef
I want to write a query which outputs the following :
1 Ab
1 Ab
2 Cd
2 Cd
3 Ef
3 Ef
Is there a way I can do it ?
I cannot think of anything except using union
Select Id, name from Table1 union select Id, name from Table1
You can use a union all. A union will not work, because it will eliminate duplicates. Another way is a cross join:
select id, name
from table1 t1 cross join
(select 1 as n union all select 2) n;
You can also use UNION ALL, put them under CTE (Common Table Expression) and Order By Id:
WITH CTE AS
(
SELECT Id, Name FROM Table_1
UNION ALL
SELECT Id, Name FROM Table_1
)
SELECT Id, Name
FROM CTE
ORDER BY Id;
As this will reorder them and stacked them as duplicates
Solution will be like this:
select Id, name from Table1
union all
select Id, name from Table1

MINUS functionality in BigQuery database

I am new to BigQuery database.
Like in Oracle database MINUS operator what is the same functionality in BigQuery? I did not find MINUS operator in BigQuery.
Oracle --> Minus
BigQuery --> ??
Though there is no MINUS function in BigQuery, you can use a LEFT OUTER JOIN as an alternative.
SELECT name, uid FROM a
MINUS
SELECT name, uid FROM b
Can be written as:
SELECT a.name, a.uid
FROM a LEFT OUTER JOIN b ON a.name= b.name AND a.uid= b.uid
WHERE b.name IS NULL
BigQuery doesn't have "MINUS", but it does have the functionally identical "EXCEPT DISTINCT".
with whole as
( select 1 as id, 'One' as value
union all
select 2 as id, 'Two' as value
union all
select 3 as id, 'Three' as value
),
sub_set as
(
select 1 as id, 'One' as value
union all
select 2 as id, 'Two' as value
)
select * from whole
except distinct
select * from sub_set
Result was
3 Three
Refer: https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#except
I am getting the error EXCEPT ALL is not supported, DISTINCT worked. Hope this helps.
StandardSQL Output for MINUS where ID is the composite key or primary key in Table 1 and Table2
same concept as Vamsi Mohan's
Select ID, Name from Table 1
where ID not in (Select distinct ID in Table 2)