I am trying to choose the row where
1)list.ispublic = 1
2)userlist.userid='aaa' AND userlist.listid=list.listid
I need 1)+2)
There is a row already but this statement can not get that row, is there any problem?
List table:
ListID ListName Creator IsRemindSub IsRemindUnSub IsPublic CreateDate LastModified Reminder
1 test2 aaa 0 0 1 2012-03-09 NULL NULL
user_list table (No row):
UserID ListID UserRights
My test version
SELECT *
FROM list l
INNER JOIN user_list ul ON ul.ListID = l.ListID
WHERE l.IsPublic = 1 AND ul.UserID = '09185346d'
This is the Result when there are two list in user_list has aaa , and one list is public in list, so will this cause double retrieve of that one public list in list if i get it in php ?
ListID ListName Creator IsRemindSub IsRemindUnSub IsPublic CreateDate LastModified Reminder UserID ListID UserRights
1 test2 aaa 0 0 1 2012-03-09 NULL aaa 1 read
2 t2 aaa 0 0 1 2012-03-09 NULL aaa 2 read
If your user_list table contains no rows, that query will return no results.
You want a LEFT JOIN.
SELECT list.col_1, list.col_2 -- etc...
FROM list
LEFT JOIN user_list ON user_list.ListID = List.ListID
WHERE list.IsPublic = 1
OR user_list.UserID = 'aaa'
First, try to only SELECT the fields you actually need. Second, write your JOINS explicitly - it helps readability. For example:
SELECT l.*, ul.*
FROM list l
INNER JOIN user_list ul ON ul.ListID = l.ListID
WHERE l.IsPublic = 1
AND ul.UserID = 'aaa'
Incidentally, if you have no data in your user_list table, then you have no way to meet the requirements you have set. If as you put it "userlist.listid=list.listid" is necessary and the user_list table is empty, you will always get zero rows returned.
Edit: And no, it won't cause rows to be retrieved double. Whatever results you get with your SQL query will be the same results you get in a PHP script - the mechanism for retrieving the data is the same.
Related
I have a table like this:
userid | trackid | path
123 70000 ad
123 NULL abc.com
123 NULL Apply
345 70001 Apply
345 70001 Apply
345 NULL Direct
345 NULL abc.com
345 NULL cdf.com
And I want a query like this. When path='abc.com', num_website +1; when path='Apply', num_apply +1
userid | num_website | num_Apply | num_website/num_Apply
123 1 1 1
345 1 2 0.5
My syntax looks like this:
select * from
(select userid,count(path) as is_CWS
from TABLE
where path='abc.com'
group by userid
having count(path)>1) a1
JOIN
(select userid,count(userid) as Apply_num from
where trackid is not NULL
group by userid) a2
on a1.userid=a2.userid
My question is
1. how to have the field num_website/num_apply in term of my syntax above?
2. is there any other easier way to get the result I want?
Any spots shared will appreciate.
The simplest way to do it would be to change the select line:
SELECT a1.userid, a1.is_CWS, a2.Apply_num, a1.is_CWS/a2.Apply_num FROM
(select userid,count(path) as is_CWS
from TABLE
where path='abc.com'
group by userid
having count(path)>1) a1
JOIN
(select userid,count(userid) as Apply_num
from TABLE
where trackid is not NULL
group by userid) a2
on a1.userid=a2.userid
and then continue with the rest of your query as you have it. The star means "select everything." If you wanted to select only a few things, you would just list those things in place of the star, and if you wanted to select some other values based on those things, you would put those in the stars as well. In this case a1.is_CWS/a2.Apply_num is an expression, and MySql knows how to evaluate it based on the values of a1.is_CWS and a2.Apply_num.
In the same vein, you can do a lot of what those subqueries are doing in a single expression instead of a subquery. objectNotFound has the right idea. Instead of doing a subquery to retrieve the number of rows with a certain attribute, you can select SUM(path="abc.com") as Apply_num and you don't have to join anymore. Making that change gives us:
SELECT a1.userid,
SUM(path="abc.com") as is_CWS,
a2.Apply_num,
is_CWS/a2.Apply_num FROM
TABLE
JOIN
(select userid,count(userid) as Apply_num
FROM TABLE
where trackid is not NULL
group by userid) a2
on a1.userid=a2.userid
GROUP BY userid
Notice I moved the GROUP BY to the end of the query. Also notice instead of referencing a1.is_CWS I now reference just is_CWS (it's no longer inside the a1 subtable so we can just reference it)
You can do the same thing to the other subquery then they can share the GROUP BY clause and you won't need the join anymore.
to get you started ... you can build on top of this :
select
userid,
SUM(CASE WHEN path='abc.com'then 1 else 0 end ) as num_website,
SUM(CASE WHEN path='Apply' and trackid is not NULL then 1 else 0 end ) as Apply_Num
from TABLE
WHERE path='abc.com' or path='Apply' -- may not need this ... play with it
group by userid
Here's the fiddle;
http://sqlfiddle.com/#!2/af8015/9
I've some data, and I want to set
if user and g parameter are in table named cl, result column should
be 1;
if user and g parameter are in table named im, but not in cl, result
column should be -1;
else, result column should be 0
I'm using following query;
select *,
case cl.user_id
when null then -1
when im.user_id then 1
end as result
from im
left join cl on cl.user_id = im.user_id
and cl.id_g = im.id_g
left join user on user.user_id = im.user_id
left join g on g.id_g = im.id_g
But, it returns null for -1, and I couldn't set 0 for the last case.
Expected result table is;
user id - g id - result
1 1 1
1 2 1
1 3 0
1 4 1
2 1 1
2 2 1
2 3 -1
2 4 0
...
I can't see a way of generating the 0 result from your sample data.
I believe your result parameter should be computed like this;
IF (cl.user_id IS NOT NULL and cl.id_g IS NOT NULL, 1,
IF(im.user_id IS NOT NULL and im.id_g IS NOT NULL, -1,0)
) result
And, I think your series of JOIN operations should go like this.
FROM user
LEFT JOIN im ON user.user_id = im.user_id
LEFT JOIN cl ON user.user_id = cl.user_id AND im.id_g = cl.id_g
LEFT JOIN g ON im.id_g = g.id_g
That is, you should lead with the user table. Here's an example: http://sqlfiddle.com/#!2/a5c6ef/1/0
Your result parameter is computed like this:
case cl.user_id
when null then -1
when im.user_id then 1
end as result
null values work strangely. A null value can never compare equal to anything, even another null value, so when null then -1 will never fire. This expression, on the other hand, should work.
case when cl.user_id IS NULL then -1
when im.user_id IS NULL then 1
else 0 end as result
I got 3 tables in my MYSQL bases and I have to compare how many time there are each user_ID in each of the 2 first table (table 1 and table 2)
here is my table 1:
user_ID
A
B
A
D
...
here is my table 2 :
user_ID
A
C
A
...
here is my table 3 (with link between user_ID and nickname) :
user_ID // nickname
A // Bob
B // Joe
C // Tom
...
I would like to get a result like this:
Nickname // count occurrences from Table 1 // count occurrences from table 2
Bob // 1 // 2
Joe // 4 // 0
Tom // 0 // 2
I did not succeed for instant to count separately from each table, I got a global result for each nickname :(
Could you help me to find the right MYSQL request ?
- ...
This type of query is a little tricky, because some names may not be in the first table and others may not be in the second. To really solve this type of problem, you need to pre-aggregate the results for each query. To get all the names, you need a left outer join:
select t3.name, coalesce(cnt1, 0) as cnt1, coalesce(cnt2, 0) as cnt2
from table3 t3 left outer join
(select name, count(*) as cnt1
from table1
group by name
) t1n
on t3.name = t1n.name left outer join
(select name, count(*) as cnt2
from table2
group by name
) t2n
on t3.name = t1n.name;
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.
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 )