This table lists user and item id's
user_id item_id
1 1
1 2
1 3
2 1
2 3
3 1
3 4
3 3
How can I run a query on this table to list all the items that are common between given users.
My guess is, this will need a self join, but I'm not sure.
i am trying this quering but it's returning an error
SELECT *
FROM recs 1
JOIN recs 2 ON 2.user_id='2' AND 2.item_id=1.item_id
WHERE 1.user_id='1'
Try using alias names that start in a letter:
SELECT *
FROM recs r1
JOIN recs r2 ON r2.user_id='2' AND r2.item_id=r1.item_id
WHERE r1.user_id='1'
This returns
user_id item_id
------- -------
1 1
1 3
for your data. Demo on sqlfiddle.
Note: I kept single quotes in the query, because I assume that both IDs in your table are of character type. If that is not the case, remove single quotes around user ID values '1' and '2'.
I want it for n number of users ... a I want the query to return all item_id's that are common among the users
SELECT DISTINCT(r1.item_id)
FROM recs r1
WHERE EXISTS (
SELECT *
FROM recs r2
WHERE r2.item_id=r1.item_id
AND r1.user_id <> r2.user_id
)
Demo #2.
Related
I have 3 Tables
campaign1 (TABLE)
id campaign_details
1 'some detail'
campaign2 (TABLE)
id campaign_details
1 'some other detail'
campaign_list (TABLE)
id campaign_table_name
1 'campaign1'
2 'campaign2'
Campaign list table contains the table name of the two tables described above. I want to Select from the Campaign List table and get the record count using the table name i get from this select
For eg.
using select i get campaign1(Table name). Then i run select query on campaign1 to count number of records.
What i'm doing right now is .
-Select from campign_list
-loop through all campaign_table_names and run select query individually
Is there a way to do this using a single query
something like this
select campaign_name,(SELECT COUNT(*) FROM c.campaign_name) as campcount from campaign_list c
SQLFiddle : http://sqlfiddle.com/#!9/b766d/2
It's not possible inside a single query to build it dynamically but it's possible to cheat. Especially if there are only two linked tables.
I've listed two options
left outer join both tables
select campaign_name,
coalesce(c1.campaign_details, c2.campaign_details)
from campaign_list c
left join campaign1 c1 using (id)
left join campaign2 c2 using (id);
union all two different selects
select campaign_name,
campaign_details
from campaign_list c
join campaign1 c1 using (id)
union all
select campaign_name,
campaign_details
from campaign_list c
join campaign2 c2 using (id);
sqlfiddle
Combine your campaign tables to 1 table and add an column named 'type' (int).
campaign_items tables:
item_id item_details item_type
1 'some detail' 1
2 'some detail' 1
3 'some other detail' 2
4 'some other detail' 2
campaign_lists table
campaign_id campaign_name
1 'campaign1'
2 'campaign2'
Then you can use the following select statement:
SELECT campaign_name, (SELECT COUNT(*) FROM campaign_items WHERE item_type = campaign_id) as campaign_count
FROM campaign_lists
Oops, writing took me so long that you got this answered by Colin Raaijmakers already. Well, I'll post my answer anyway in spite of being more or less the same answer. Maybe my elaboration helps you see the problem.
Your problem stems from a bad database design. A database is made to order data and its relations. A CD database holds albums, songs, artists, etc. A business database may hold items, warehouses, sales and so on. Your database holds table names. [... time for thinking :-) ]
(When writing a DBMS you would want to store table names, column names, constraints etc., but I guess I am right supposing that you are not writing a new DBMS.)
So create tables that deal with your actual data. E.g.:
campain_type (id_campain_type, description, ...)
campain (id_campain, id_campain_type, campain_date, ...)
campain_type
id_campain_type description
1 Type A
2 Type B
3 Type C
campain
id_campain id_campain_type date
33 1 2015-06-03
85 2 2015-10-23
97 2 2015-12-01
query
select
ct.description,
(select count(*) from campain c where c.id_campain_type = ct.id_campain_type) as cnt
from campain_type ct;
result
description cnt
Type A 1
Type B 2
Type C 0
I have a table with data similar to this:
id job_id filename status revision product
----------------------------------------------------------
1 1 1r0.jpg P 0 Product 1
2 1 2r0.jpg P 0 Product 2
3 1 3r0.jpg P 0 Product 3
4 1 2r1.jpg P 1 Product 2
I want to run an SQL query that returns the following:
id job_id filename status revision product
----------------------------------------------------------
1 1 1r0.jpg P 0 Product 1
3 1 3r0.jpg P 0 Product 3
4 1 2r1.jpg P 1 Product 2
i.e. if there's two rows with the same product name, I want to get the one with the highest revision number.
I've tried lots of queries using groupby, max, distinct to no avail. I've tried self-joins but cannot get the results I'm after.
For example, the query SELECT *, MAX(revision) FROM artworks GROUP BY product gives me data that looks fine at first glance but the row contains the data from the one with the lowest revision number, not the highest.
You can do it without GROUP BY, like this:
SELECT *
FROM artworks a
WHERE NOT EXISTS (
SELECT *
FROM artworks aa
WHERE a.product=aa.product AND a.revision < aa.revision
)
You may get the same result without a sub-query:
SELECT a.*
FROM artworks a
left join artworks b
on a.produc = b.produc
and a.revision < b.revision
where b.id is null;
I have the following MySQL table:
id rid
----- ------
1 2
2 1
2 3
3 2
1 3
3 1
I want to change this so only one row per relation exists.
e.g:
id rid
----- ------
1 2
2 3
1 3
If you always have pairs (as in your example):
delete from table
where id > rid;
This keeps the record where id is smaller.
If there is the possibility that no all pairs exist, then:
delete t
from table t left outer join
(select least(id, rid) as lid, greatest(id, rid) as gid, count(*) as cnt
from table t2
group by least(id, rid), greatest(id, rid)
) t2
on least(t.id, t.rid) = t2.lid and greatest(t.id, t.rid) = gid
where id < rid or t2.cnt = 1;
EDIT (explanation):
How does the second query work? Let me be honest, what I want to write is this:
delete t from table t
where id < rid or
(id > rid and
not exists (select 1 from table t2 where t2.id = t.rid and t2.rid = t.id
);
That is, I want to keep all records where id < rid. But then, I also want to keep all singleton records where rid > id. I don't think MySQL allows the syntax with the where clause.
Instead, the query in the answer counts the number of times that a pair exists, by looking at the smallest value and the largest value. For the data in the question, the result of the subquery is:
id rid cnt
1 2 2
2 3 2
1 3 2
So, all of these would use the id < rid to select the row. If you had one more row, say 4, 1. It would look like:
lid gid cnt
1 2 2
2 3 2
1 3 2
1 4 1
In this case, the first three would take the row with id < rid. But the new row would also be selected because the cnt is 1.
If you had duplicates in the table and a primary key, there would be a slight variation on the query that would do the same thing.
This one is a little bit tricky, at least to me to explain, so please, don't get mad if you don't get the point - it's likely caused by my poor explanation.
I want to get one more column from my main SELECT, which will represent number of rows from another table, suiting id of main record.
So, imagine main table, which I am selecting from. I'll call it simply main.
What I want to select from main, basically is:
SELECT * FROM main ORDER BY c1 ASC LIMIT 5
Plus I need one extra column for each row returned, which says number of rows from side table, matching the id:
SELECT COUNT(*) FROM side WHERE m_id = main_id
Maybe an example will tell you a little bit more
id data1 data2 id m_id ...
main ----|-------|------- side -----|------|-----
1 aa ab 1 1
2 xx yy 2 2
3 az bz 3 1
4 1
5 3
6 2
7 1
8 1
9 2
expected result:
id data1 data2 num
----|-------|-------|------
1 aa ab 5
2 xx yy 3
3 az bz 1
A simple way to add the count is with a correlated subquery:
SELECT m.*,
(select count(*) from side s where s.m_id = m.main_id) as side_cnt
FROM main m
ORDER BY c1 ASC
LIMIT 5;
You can also do this by changing the from clause. However, this method only affects the select part of the query.
You should be able to do it as a subquery:
SELECT m.*, ( SELECT COUNT(*) FROM side WHERE m_id = m.main_id ) as num FROM main m ORDER BY c1 ASC LIMIT 5
This basically runs a special query for each result that counts the number of matching results and displays it in the "num" column.
I request some help with MySQL when-then statement to fetch all the sid from the table after comparing multiple records having same sid but different cid-data values:
flag sid cid data
---- --- --- ----
1 300 1 john
1 300 2 john_email
1 300 3 77500
1 300 4 ok
1 301 1 jack
1 301 2 john_email
1 301 3 72210
1 301 4 notok
Here for each sid, I need to check if (sid=2 has data=john_email) AND (sid=4 has data=ok)
Only if both the conditions are satisfied, I return the sid. i.e. the output will be '300' only.
I am confused how to use the case-when-then and compare 'data' with 'john_email' and also compare data with 'ok' ... based on the cid values. Thanks for reading.
try
select sid
from your_table
group by sid
where (cid=2 and data='john_email')
or (cid=4 and data='ok')
having sum(cid=2)=1 and sum(data='john_email')=1
and sum(cid=4)=1 and sum(data='ok')=1
SQLFiddle example
You should join the table to itself, then you can check the condition in the two rows as if it was one row...
SELECT T1.sid
FROM MYTABLE T1
JOIN MYTABLE T2 ON T1.SID=T2.SID AND T1.CID=1 AND T2.CID=4
WHERE T1.DATA='john'
AND T2.DATA='ok'
Note that I used the CID values in the join clause, but you will have to adjust them if you want to join on different data rows...
What you can do is use a subquery and check if the value exists.
SELECT
*
FROM
table outertable
WHERE
( cid=2 AND data='john_email' )
AND
EXISTS ( SELECT sid FROM table WHERE cid = 4 AND data = 'ok' AND sid = outertable.sid )