combining similar rows with two same values - sql

I have three tables: users, products and reviews. I'm trying to get form a table that would show products that have gotten the same review from different users, the users who reviewed it and what review it got.
Here are the tables and the output I'm looking for:
Users
uid uname
1 name1
2 name2
3 name3
4 name4
Products
pid pname
1 A
2 B
3 C
4 D
Reviews
pid uid grade
1 1 3
1 2 2
1 3 3
2 1 4
3 2 1
2 2 4
4 3 1
Desired output:
uname uname2 pname grade
name1 name3 A 3
name3 name1 A 3
name1 name2 B 4
name2 name1 B 4

There are some overly complicated answers here.
Its pretty simple using a self join like this:
select u1.uname, u2.uname, p.pname, r1.grade
from review r1
join review r2 on r2.pid=r1.pid and r2.grade=r1.grade and r2.uid<>r1.uid
join products p on p.pid=r1.pid
join users u1 on u1.uid=r1.uid
join users u2 on u2.uid=r2.uid
order by pname, r1.grade, u1.uname, u2.uname
Result:
uname uname1 pname grade
name1 name3 A 3
name3 name1 A 3
name1 name2 B 4
name2 name1 B 4

select users.uname, reviews.grade, products.pname from products
join reviews on products.id = reviews.pid
join users on users.id = reviews.id

This can be done using a self-join like this -
with combined as
(select (select uname from users where uid = r.uid),
(select pname from products where pid = r.pid),
r.grade,
r.uid
from reviews r)
select c1.uname as name1, c2.uname as name2, c1.pname, c1.grade
from combined c1, combined c2
where c1.grade = c2.grade
and c1.pname = c2.pname
and c1.uid <> c2.uid;

Related

Select rows with specific multiple values from the same column?

I have database where 2 roles can't be associated with each other, and I need to display any users who have conflicting roles.
For example: an (id 2) accountant can't also be a (id 5) trainer
this has to be done without using CTE's
Table a Table b table c
--------------- ------------------- ------------
userID | roleID roleID | conflictID roleID | Role Name
1 2 2 5 1 chef
1 3 2 accountant
1 5 3 driver
2 3 4 barmaid
2 1 5 trainer
3 2
3 3
the result should contain only the userID who has both roles 2 and 5
userID
------
1
Join the b table with the a table twice, to get userID's with conflicting combinations:
select distinct a1.userid
from tableb b
join tablea a1 on b.roleID = a1.roleID
join tablea a2 on b.conflictID = a2.roleID
and a1.userID = a2.userID

SQL Join on multiple columns of a row

I have the following table IDDetails:
ID1 ID2 ID3
1 2 3
1 5 7 and so on
I want to link each ID of the row with a name from the Names table:
ID Name
1 A
2 B
3 C
4 D
5 E
7 G
The output should have 6 columns like :
ID1 Name1 ID2 Name2 ID3 Name3
1 A 2 B 3 C
1 A 5 E 7 G
The operation should have minimum joins with limited cost.
This query will give you the results you want. Note that you have to JOIN the Names table 3 times to get the three different names for each row.
SELECT i.ID1, n1.Name AS Name1,
i.ID2, n2.Name AS Name2,
i.ID3, n3.Name AS Name3
FROM IDDetails i
JOIN Names n1 on n1.ID = i.ID1
JOIN Names n2 on n2.ID = i.ID2
JOIN Names n3 on n3.ID = i.ID3
Output:
ID1 Name1 ID2 Name2 ID3 Name3
1 A 2 B 3 C
1 A 5 E 7 G
Update
Here is a query without JOINs, as requested in the edit after the original post:
SELECT i.ID1, (SELECT Name FROM Names n WHERE n.ID = i.ID1) AS Name1,
i.ID2, (SELECT Name FROM Names n WHERE n.ID = i.ID2) AS Name2,
i.ID3, (SELECT Name FROM Names n WHERE n.ID = i.ID3) AS Name3
FROM IDDetails i
Output:
ID1 Name1 ID2 Name2 ID3 Name3
1 A 2 B 3 C
1 A 5 E 7 G
SQLFiddle Demo of both queries

SQL Join on 2 Tables

i've been trying to build this query. hoping someone can help.
I have 2 tables.
1 table contains
Code | name | Value | Period
1 name1 1 2010
2 name2 2 2010
table 2 contains
code | name |
1 name1
2 name2
3 name3
4 name4
what i want to be displayed is
1 name1 1
2 namw2 2
3 name3 0
4 name4 0
In some instances table 1 may have a value for all name variables in table 2
but where there are only 1,2,3 names i want it to display the other one but with a value of 0 or blank.
Try this:
select
T2.*,
isnull(T1.code, 0) as code -- or value
from
table2 T2
left outer join table1 T1 on T1.name = T2.name
You can replace isnull(T1.code, 0) as code with isnull(T1.value, 0) as value. I'm not sure what you're after ...

SQL Select values associated with keys from other table

I have a mapping table tableA
key value
-----------
1 "John"
2 "George"
3 "Kate"
4 "loves"
5 "hates"
and another tableB that contains rows based on keys of tableA
col1 col2 col3
------------------
1 5 2
2 4 3
3 4 1
I want to write a selection query which will return rows from table B but replaced with their appropriate values.
e.g. the output has to be:
John | hates | George
George | loves | Kate
Kate | loves | John
Thank you.
SELECT A1.value, A2.value, A3.value
FROM tableB
JOIN tableA as A1 ON tableB.col1 = A1.key
JOIN tableA as A2 ON tableB.col2 = A2.key
JOIN tableA as A3 ON tableB.col3 = A3.key;
You should probably put the last 2 items, 'loves' and 'hates', into a separate table as they represent a different type of data than the other 3.
Here are the tables:
users:
id name
----------
1 John
2 Edward
3 Kate
feelings:
id type
----------
1 love
2 hate
feelings_users:
id user1_id feeling_id user2_id
-----------------------------------
1 1 2 2
2 2 1 3
3 3 1 1
and here's the query:
select `Ua`.`name`, `F`.`type`, `Ub`.`name` from `feelings_users` as `X`
left join `users` as `Ua` on `X`.`user1_id` = `Ua`.`id`
left join `feelings` as `F` on `X`.`feeling_id` = `F`.`id`
left join `users` as `Ub` on `X`.`user2_id` = `Ub`.`id`
and it will output:
name type name
--------------------
John hate Edward
Edward love Kate
Kate love John

SQL: Select from many-many through, joined on conditions in through table

Can't get my head around this...
I have 3 tables like this:
Computers
---------
Id
Name
ComputerLogins
--------------
Computer_Id
User_Id
NumberOfLogins
Users
-----
Id
Name
Computers "have and belong to many" Users "through" ComputerLogins.
Sample data:
Computers: Id Name
1 "Alpha"
2 "Beta"
3 "Gamma"
Users: Id Name
1 "Joe"
2 "Fred"
ComputerLogins: Computer_Id User_Id NumberOfLogins
1 1 5
1 2 12
2 1 10
2 2 6
3 1 2
3 2 4
I'm trying to construct a view that will output one row for each record in Computers, and join a Users row through MAX(NumberOfLogins) in ComputerLogins.
Desired output:
Computer_Id User_Id NumberOfLogins
1 2 12
2 1 10
3 2 4
Can you suggest a view query that will produce the desired output?
Thanks!
SELECT
CL.*, U.* --change this as needed
FROM
(
SELECT
Computer_ID, MAX(NumberOfLogins) AS NumberOfLogins
FROM
ComputerLogins
GROUP BY
Computer_ID
) maxC
JOIN
ComputerLogins CL On maxC.Computer_ID = CL.Computer_ID AND maxC.NumberOfLogins = CL.NumberOfLogins
JOIN
Users U On CL.User_ID = U.ID
Wrap in a view etc
Use:
CREATE VIEW your_view AS
SELECT c.id AS computer_id,
u.id AS user_id,
COUNT(*) AS NumberOfLogins
FROM COMPUTERS c
JOIN COMPUTERLOGINS cl ON cl.computer_id = c.id
JOIN USERS u ON u.id = cl.user_id
GROUP BY c.id, u.id