Joining multiple select queries on same table PostgreSql - sql

Below is the sample table structure what I have got,
C1 C2 C3 C4
A D G X
B E H X
C F I X
select C2 as 1_C2, C3 as 1_C3 from table1 where C1 = A and C4=X
select C2 as 2_C2, C3 as 2_C3 from table1 where C1 = B and C4=X
select C2 as 3_C2, C3 as 3_C3 from table1 where C1 = C and C4=X
Above are the three select statements what I have got. Now I need to join all three select statements and get just one row as the output like,
1_C2 2_C2 3_C2 1_C3 2_C3 3_C3
D E F G H I
Saw multiple other posts but didn't match this requirement. Any help is highly appreciated.

You could use a CASE expression, combined with MAX():
select MAX(CASE WHEN C1 = 'A' THEN C2 END) as 1_C2,
MAX(CASE WHEN C1 = 'B' THEN C2 END) as 2_C2,
MAX(CASE WHEN C1 = 'C' THEN C2 END) as 3_C2,
MAX(CASE WHEN C1 = 'A' THEN C3 END) as 1_C3,
MAX(CASE WHEN C1 = 'B' THEN C3 END) as 2_C3,
MAX(CASE WHEN C1 = 'C' THEN C3 END) as 3_C3
from table1
where C1 in ('A', 'B', 'C')
and C4 = 'X';

Related

SQL group by count unique values into separate columns

I have two columns, a and b, and both have categorical values. Say the database looks like this,
a b
a1 b1
a2 b2
a3 b1
......
I want to group by a and count unique values of b into separate columns, for example,
Value b1 b2 b3
a1 5 10 3
a2 4 6 7
....
I tried SELECT a, b, count(b) FROM table GROUP BY a, b and got something similar like this:
a1 b1 5
a1 b2 10
....
What's the SQL query to produce the desired output? Thanks.
Below is for BigQuery Standard SQL
SELECT
a,
COUNTIF(b = 'b1') AS b1,
COUNTIF(b = 'b2') AS b2,
COUNTIF(b = 'b3') AS b3
FROM t
GROUP BY a
-- ORDER BY a
You can perform conditional addition. For example:
select
a,
sum(case when b = 'b1' then 1 else 0 end) as b1,
sum(case when b = 'b2' then 1 else 0 end) as b2,
sum(case when b = 'b3' then 1 else 0 end) as b3
from t
group by a
order by a
A simple approach to achieve would be:
Select a,
count(CASE WHEN b = 'b1' THEN 1 ELSE NULL END) b1,
count(CASE WHEN b = 'b2' THEN 1 ELSE NULL END) b2,
count(CASE WHEN b = 'b2' THEN 1 ELSE NULL END) b3
from table
group by a
order by 1

Looking for an alternative SQL statement

Given the following table with 2 columns:
c1 c2
------------
a1 | b1
a1 | b1
a2 | b2
a2 | b3
a3 | b3
I want to return those values from column c2 where the value of c2 column appears multiple times for the same c1 value. I am doing the following SQL query to return the required result:
SELECT DISTINCT ( c2 ) AS c
FROM ( SELECT c1 , c2 , COUNT (*) AS rowcount
FROM table
GROUP BY c1 , c2 HAVING rowcount > 1 )
Result:
c
---
b1
Is there any alternative SQL statement of the above query?
Based on your description, you can use:
select distinct c1
from (select t.*, count(*) over (partition by c2) as cnt
from t
) t
where cnt >= 2;
Based on your sample results:
select c1
from t
group by c1
having count(*) >= 2;
And based on the revised question:
select c2
from t
group by c2
having count(*) >= 2;
Use count in having clause instead of using subquery:-
select c1
from table
group by c1
having count(c2) > 1
Most answers above will work if you want all the values in c1 that appear more than once in the table (even with the same value on c2).
If you want to measure only values of c1 that may have multiple DISTINCT values on c2 you can use:
SELECT c1
FROM table
GROUP BY c1
HAVING COUNT(DISTINCT c2) > 1

NESTED GROUP BY QUERY

I have below relation:
C(id, n)
I(id,g)
IB(I_id, c_id, r)
I want to list all "n" from relation "C" in which their r equals 'H' and maximum "g" equals 't'
Sample data will be as below:
C:
C_ID , N
c1 , N1
c2 , N2
c3 , N3
IB:
C_ID , I_ID , R
c1 , i1 , H
c1 , i2 , H
c1 , i3 , N max H for c1 is t and m
c2 , i1 , N
c2 , i2 , H
c2 , i3 , N max H for C2 is m
c3 , i1 , H
c3 , i2 , H
c3 , i3 , H max H for c3 is t
I:
I_ID , G
i1 , t
i2 , m
i3 , t
For this sample data c1 and c3 have maximum 'H' for 't'
Below query is one answer but seem it is not optimized and very heavy:
SELECT c1.n
FROM I ib1, C c1, I i1
WHERE i1.I_ID = ib1.I_ID
AND i1.g IN
(SELECT i.g
FROM IB ib, C c, I i
WHERE i.id = ib.I_id
AND c.id = ib.C_id
AND ib.r = 'H'
AND i.g = 't'
AND c.id = c1.id
GROUP BY i.g, c.id
HAVING COUNT(*)=(
SELECT max(COUNT(*))
FROM IB ib, C c, I i
WHERE i.id = ib.I_id
AND c.ID = ib.C_id
AND ib.r = 'H'
AND c.id = c1.id
GROUP BY i.g, c.id))
GROUP BY c1.id, c1.name;
It is appreciated to let me know what are other possible solutions and how I can optimize my query. Also it is worth to help me with my table design as well.
Thanks
If I understand correctly, with the group by we get the count per c.id,i.g, then we 'number' the rows in descending order by count and we get only the first rows with i.g='t'
SELECT DISTINCT c1.n
FROM C c1
WHERE c1.c_id IN (SELECT DISTINCT x.c_id
FROM (SELECT c_id, g, RANK () OVER (PARTITION BY c_id ORDER BY cnt DESC) rnmbr
FROM ( SELECT c.c_id, i.g, COUNT (*) cnt
FROM IB ib, C c, I i
WHERE i.i_id = ib.I_id AND c.c_ID = ib.C_id AND ib.r = 'H'
GROUP BY i.g, c.c_id)) x
WHERE g = 't' AND rnmbr = 1)

How to reference result from previous 2 column like Excel formular

SELECT
Answer_Code AS C0,
Text AS C1,
Price AS C2,
sum(case when Response like '%PAID%' then 1 else 0 end) AS C3,
C2 * C3 AS 'Total' --Invalid column name 'C2'.--
FROM TableA
How to reference C2 and C3, then do multiplication in that position ?
Any techniques ?
You can use inner-select:
SELECT *, C2 * C3 As Total
FROM (
SELECT
Answer_Code AS C0,
Text AS C1,
Price AS C2,
sum(case when Response like '%PAID%' then 1 else 0 end) AS C3,
FROM TableA) DT;
or use a CTE like this:
;WITH t AS (
SELECT
Answer_Code AS C0,
Text AS C1,
Price AS C2,
sum(case when Response like '%PAID%' then 1 else 0 end) AS C3,
FROM TableA)
SELECT *, C2 * C3 As Total
FROM t;
You can use with clause or a sub query.
;with tmp_tbl as (
SELECT
Answer_Code AS C0,
Text AS C1,
Price AS C2,
sum(case when Response like '%PAID%' then 1 else 0 end) AS C3
--C2 * C3 AS 'Total' --Invalid column name 'C2'.--
FROM TableA
)
select
C0,
C1,
C2,
C3,
C2 * C3 AS 'Total'
from tmp_tbl;

Query to update row which contains maximum column value in MS SQL 2008

I have a table similar to below:
C1 C2 C3
A 5 0
A 15 0
A 2 0
B 5 0
B 8 0
Result table updates C3 with 1 for mac value of C2 group by C1
C1 C2 C3
A 5 0
A 15 1
A 2 0
B 5 0
B 8 1
For SQL Server 2005+:
;WITH CTE AS
(
SELECT *,
MAX(C2) OVER(PARTITION BY C1) MaxC2
FROM YourTable
)
UPDATE CTE
SET C3 = CASE WHEN MaxC2 = C2 THEN 1 ELSE 0 END
Supossing table is named table_name
UPDATE t1 SET t1.C3 = 1
FROM table_name as t1 INNER JOIN (
SELECT C1, MAX(C2) AS C2 FROM table_name GROUP BY C1
) AS t2 ON t1.C1 = t2.C1 AND t1.C2 = t2.C2