Query to show one column multiplied - sql

I have the following 3 tables;
Table_Names:
user_id Name
------------------
1 Mark
2 Tom
3 Ana
Table_Language:
language_id Language
-----------------------
1 English
2 German
Table_Name_Lang
id user_id language_id
---------------------------
1 1 1
2 1 2
3 2 1
4 3 2
How can I create a query to show the expected results like those below?
Name Expr_1_Eng Expr_1_Ger
---------------------------------
Mark English German
Tom English
Ana German
Thanks Tok

I would do:
select n.name,
max(case when l.language = 'English' then l.language end) as has_English,
max(case when l.language = 'German' then l.language end) as has_German
from names n join
name_lang nl
on nl.user_id = n.user_id join
lang l
on nl.language_id = l.language_id
group by n.name

You can try to use JOIN with condition aggregate function
SELECT Name,
MAX(CASE WHEN tnl.language_id = 1 then tl.Language end),
MAX(CASE WHEN tnl.language_id = 2 then tl.Language end)
FROM
Table_Name_Lang tnl
JOIN Table_Names tn on tnl.language_id = tn.language_id
JOIN Table_Language tl on tl.user_id = tnl.user_id
GROUP BY Name

I think you should use pivot:
select n.name,[0] as language_one,[1] as language_two,[2],[3] from
(select n.name,tl.language
tablename n
left join Table_Name_Lang tnl on n.userid=tnl.userid
left join table_language tl on tl.id=tnl.id
group by n.name,tl.language
)T
pivot
(
language
for name in [0],[1],[2],[3]
)AS PivotTable;

Related

Denormalization table - SQL Select (Pivot Table?)

CAMPAIGN table
ID
campaign_name
1
Campaign A
2
Campaign B
PARTICIPANT table
ID
campaign_id
participant_name
1
1
Alice
2
1
Ben
CUSTOM_FIELD table
ID
campaign_id
field_name
1
1
Gender
2
1
Age
FIELD_ANSWER table
ID
participant_id
field_id
answer
1
1
1
Female
2
1
2
24
3
2
1
Male
4
2
2
28
With these tables in above, can we query a result as shown below?
Campaign Name
Participant Name
Gender
Age
Campaign A
Alice
Female
24
Campaign A
Ben
Male
28
Using pivoting logic we can try:
SELECT
c.campaign_name,
p.participant_name,
MAX(CASE WHEN cf.field_name = 'Gender' THEN fa.answer END) AS Gender,
MAX(CASE WHEN cf.field_name = 'Age' THEN fa.answer END) AS Age
FROM CAMPAIGN c
INNER JOIN PARTICIPANT p
ON p.campaign_id = c.ID
INNER JOIN FIELD_ANSWER fa
ON fa.participant_id = p.ID
INNER JOIN CUSTOM_FIELD cf
ON cf.ID = fa.field_id AND cf.campaign_id = c.ID
GROUP BY
c.campaign_name,
p.participant_name;
Here is a demo in SQL Server, though the above query should run on most other database as well.

SQL query to get info from different tables

Need a help with sql query.
I have 2 tables.
Matches.
first_referee_arbitr_id
second_referee_arbitr_id
home_team
guest_team
date
Arbitrs.
id
name
surname
first_referee_arbitr_id and second_referee_arbitr_id are from Arbitrs table(id).
As the result I need to count how much each referee has been included in matches:
referee_first_count | referee_second_count | Arbitr Surname | Arbitr Name
My query now:
SELECT T1.referee_first_count, T2.referee_second_count, T1.surname, T1.name
FROM (
select matches.first_referee_arbitr_id, q.surname, q.name, count(*) AS referee_first_count
FROM matches
JOIN (
SELECT name, surname, id
FROM arbitrs
) as q ON matches.first_referee_arbitr_id=q.id
GROUP BY matches.first_referee_arbitr_id, q.name, q.surname
ORDER BY referee_first_count DESC
) T1 FULL OUTER JOIN
(
select matches.second_referee_arbitr_id, arbitr.surname, arbitr.name, count(*) AS referee_second_count
FROM matches
JOIN (
SELECT name, surname, id
FROM arbitrs
) as arbitr ON matches.second_referee_arbitr_id=arbitr.id
GROUP BY matches.second_referee_arbitr_id, arbitr.name, arbitr.surname
ORDER BY referee_second_count DESC
) T2
ON (
(T1.name = T2.name) AND (T1.surname = T2.surname)
)
Example
Arbitrs:
id | Name | Surname
1 John Rambler
2 Steve Crystler
3 Tom Ferguson
Matches:
first_referee_arbitr_id| second_referee_arbitr_id| home_team | guest_team | date
1 Chelsea Everton 22.06.2020
2 1 Liverpool Lester 28.06.2020
3 Dinamo K Dinamo M 06.07.2020
1 2 Juventus Dinamo K 10.10.2020
3 Dinamo K Chelsea 20.20.2020
Result:
referee_first_count | referee_second_count | surname | name
2 1 Rambler John
1 1 Crystler Steve
2 0 Ferguson Tom
My result now with query above:
referee_first_count | referee_second_count | surname | name
2 1 Rambler John
1 1 Crystler Steve
2 NULL NULL NULL
First aggregate the matches table (twice) and left join this to the Arbitrs table:
SELECT a.name , a.Surname , ISNULL(fir.first_count,0) , ISNULL( sec.sec_count,0)
FROM Arbitrs a
LEFT JOIN (
SELECT first_referee_arbitr_id,COUNT(*) as first_count
FROM Matches
GROUP BY first_referee_arbitr_id
) fir
ON fir.first_referee_arbitr_id = a.id
LEFT JOIN (
SELECT second_referee_arbitr_id,COUNT(*) as sec_count
FROM Matches
GROUP BY second_referee_arbitr_id
) sec
ON sec.second_referee_arbitr_id = a.id
SELECT
a.name
, a.surname
, COUNT(CASE WHEN m1.id IS NOT NULL THEN 1 end) referee_first_count
, COUNT(CASE WHEN m2.id IS NOT NULL THEN 1 end) referee_second_count
FROM
Arbitrs a
LEFT JOIN macthes m1
ON a.id = m.first_referee_arbitr_id
LEFT JOIN macthes m2
ON a2.id = m.second_referee_arbitr_id
GROUP BY
a.name
, a.surname
-- if you want to show only those with refrence
HAVING referee_first_count > 0 or referee_second_count > 0

join two SQL rows in a single one

I have three tables in Postgresql, for a biological classification system.
table lang (languages)
id name
1 português
2 english
-------------------------------
table taxon (biological groups)
id name
...
101 Mammalia
-------------------------------
table pop (popular names)
id tax lang pop
...
94 101 1 mamíferos
95 101 2 mammals
I want to get
id name namePT nameEN
101 Mammalia mamíferos mammals
but my join is giving me
id name pop
101 Mammalia mamíferos
101 Mammalia mammals
select t.id,name,pop from taxon t
left join pop p on p.tax = t.id
where t.id = 101
How can I get the desired result in a single row?
If you are happy to change query every time you add a new language then this query will do the trick:
select t.id,name,pe.pop as eng_pop, pp.pop as port_pop
from taxon t
left join pop pe on pe.tax = t.id and pe.lang = 1
left join pop pp on pp.tax = t.id and pp.lang = 2
where t.id = 101
You could use this
SELECT t.id, t.name,
MAX(CASE WHEN p.lang = 1 THEN p.pop END) AS namePT,
MAX(CASE WHEN p.lang = 2 THEN p.pop END) AS nameEN
FROM taxon t
LEFT JOIN pop p
ON p.tax = t.id
GROUP BY t.id, t.name;
Here's how I got the results:
with base as (
select t.id, t.name,
case when lang = 1 then 'mamiferos' else null end as namePT,
case when lang = 2 then 'mamals' else null end as nameEN
from taxon t
left join pop p on t.id = p.tax
group by 1,2,3, p.lang
)
select
distinct id,
name,
coalesce(namept,'mamiferos',null) as namept,
coalesce(nameen,'mamals',null) as nameen
from base
where id = 101
group by id, name, namept, nameen;
id | name | namept | nameen
-----+----------+-----------+--------
101 | Mammalia | mamiferos | mamals
(1 row)

Use Count function inside conditional part of Case Expression

I have two tables with the following sample records in oracle database
1. staffs
inst_name name sid
ABC John 1
PQR Sam 2
ABC Tom 3
ABC Amit 4
PQR Jack 5
2. staffaccounts
sid account_no
1 4587
1 4588
2 4589
3 4581
3 4582
5 4583
5 4585
4 4586
Where I want the result like
inst_name account_type total
PQR SINGLE 1
ABC SINGLE 1
PQR DOUBLE 1
ABC DOUBLE 2
This can be achieved by a outer query, but I want to write a query where there is no outer query. Want to accomplish it in one single query.
SELECT
A .inst_name,
(
CASE COUNT (b.ac_no)
WHEN 1 THEN
'Single'
WHEN 2 THEN
'Double'
END
) account_type,
COUNT (A . NAME)
FROM
staffs A,
staffaccounts b
WHERE
A . s_id = b.s_id
GROUP BY
A .inst_name
The above query gives error ORA-00907: missing right parenthesis. Can it be done in single query or is outer query the only way out.
Oracle Version is 10g
May be something like this would work.
SELECT
A.inst_name,
CASE COUNT (b.account_no)
WHEN 1 THEN
'Single'
WHEN 2 THEN
'Double'
END account_type,
COUNT (A.name)
FROM
staffs A JOIN
staffaccounts b
ON
A.SID = b.sid
GROUP BY
A.inst_name , a.sid
ORDER BY 3;
You are grouping by inst_name, but this is not what you actually want, because you don't want a result row per inst_name, but per inst_name and account_type.
select
s.inst_name,
sa.account_type,
count(*) as total
from staffs s
join
(
select
sid,
case when count(*) = 1 then 'SINGLE' else 'DOUBLE' end as account_type
from staffaccounts
group by sid
having count(*) <= 2
) sa on sa.sid = s.sid
group by sa.account_type, s.inst_name
order by sa.account_type, s.inst_name;
You should learn how to properly use JOIN syntax. I prefer the explicit comparison syntax for CASE.
This may be what you want:
SELECT s.inst_name,
(CASE WHEN COUNT(sa.ac_no) = 1 THEN 'Single'
WHEN COUNT(sa.ac_no) = 2 THEN 'Double'
END) as account_type,
COUNT(*)
FROM staffs s JOIN
staffaccounts sa
ON s.SID = sa.sid
GROUP BY s.inst_name;
EDIT:
Now I see what you want:
SELECT s.inst_name,
(CASE WHEN cnt = 1 THEN 'Single'
WHEN cnt = 2 THEN 'Double'
END) as account_type,
COUNT(*)
FROM (SELECT s.*, COUNT(*) as cnt
FROM staffs s JOIN
staffaccounts sa
ON s.SID = sa.sid
GROUP BY s.id
) s
GROUP BY s.inst_name,
(CASE WHEN cnt = 1 THEN 'Single'
WHEN cnt = 2 THEN 'Double'
END);
I got only the way by using subquery but is in the easy way (more easier and readable) to achieve your requirement
SELECT inst_name, account_type, count(total) as total
FROM (
SELECT
a.inst_name,
CASE
WHEN COUNT (b.account_no) = 1 THEN 'Single'
WHEN COUNT (b.account_no) = 2 THEN 'Double'
END AS account_type,
COUNT (a.name) AS total
FROM staffs a
INNER JOIN staffaccounts b ON A . SID = b.sid
GROUP BY a.inst_name, a.sid) t GROUP BY inst_name, account_type
OUTPUT:
inst_name account_type total
ABC Double 2
PQR Double 1
ABC Single 1
PQR Single 1

Get separate count for each condition within group

I am trying to get a view of table information from and Oracle 10g table that lists the counts of specific values of a column in their own columns with each row being the group value.
for example:
The first select is :
SELECT processed_by, count(priority) as P2
FROM agreement_activity
WHERE priority = '2'
GROUP BY processed_by
Which outputs:
PROCESSED_BY P2
------------------------------ ----------
Alicia 2
Christine 2
The second select is:
SELECT processed_by, count(priority) as P1
FROM agreement_activity
WHERE priority = '1'
GROUP BY processed_by
Which outputs:
PROCESSED_BY P1
------------------------------ ----------
Bonita 2
Alicia 6
Christine 2
What I am looking for is to output those values as the following:
PROCESSED_BY P1 P2
------------------------------ ---------- ----------
Bonita 2
Alicia 6 2
Christine 2 2
Is that possible?
You can use sum with the case expression to get conditional count:
select processed_by
, sum(case when priority = 1 then 1 else 0 end) as P1
, sum(case when priority = 2 then 1 else 0 end) as P2
from agreement_activity
group by processed_by
P.S. If you don't care that P1 or P2 maybe null instead of 0 you can omit else in both expressions.
this is how I implement the sql. I'm using firebird code but I think you can convert the code into your sql
SELECT
a.equipmentid,
a.name equipname,
w1.countwarranty1 ,
w2.countwarranty2
FROM TBL_EQUIPMENTMST a
inner JOIN
(select c.equipmentid, count(c.WARRANTYID) countwarranty1 from tbl_equipwarranty c where c.serviceproduct='1' group by c.equipmentid) w1
ON w1.equipmentid = a.equipmentid
inner JOIN
(select d.equipmentid, count(d.WARRANTYID) countwarranty2 from tbl_equipwarranty d where d.serviceproduct='2' group by d.equipmentid) w2
ON w2.equipmentid = a.equipmentid
inner JOIN
(select e.equipmentid, count(e.equiplocationid) countlocation from tbl_equiplocation e group by e.equipmentid) w3
ON w3.equipmentid = a.equipmentid
this is the output
My warranty table has only 2 warranty for equipment each that's why its only showing 2.
you can also inner join to the same table with different count.
as you can see my warranty has multiple warranty where serviceproduct is different on each table
if I edit your code it will be like this
SELECT a.processed_by, b.priority as p2, c.priority as p1
FROM agreement_activity a
inner join
(
SELECT w1.processed_by, count(w1.priority) as P2 FROM agreement_activity w1
WHERE w1.priority = '2' GROUP BY w1.processed_by
) b
on a.processed_by = b.processed_by
inner join
(
SELECT w2.processed_by, count(w2.priority) as P2 FROM w2.agreement_activity
WHERE w2.priority = '1' GROUP BY w2.processed_by
) c
on a.processed_by = c.processed_by
test it