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
Related
From every row from the main table, I want to obtain the ColWanted value from the mapping table. For example, for the main table row with id 100 I should obtain 'one', for the id 101 I should obtain 'two', for the 102 'one', 103 'one', etc.
Is it possible?
Main table
PkId
CAT
UP
100
1
1
101
1
2
102
2
1
103
1
3
Mapping table
CAT
UP
ColWanted
1
null
one
1
2
two
2
null
one
Update 1
I tried proposed solutions, like:
SELECT m.PkId, m.CAT mCAT, m.UP mUP, p.ColWanted pColWanted, p.CAT pCAT, p.UP pUP
FROm m
LEFT JOIN p ON
m.CAT = p.CAT AND
m.Up = COALESCE(p.Up, m.Up)
WHERE m.PkId = 101
PkId
mCAT
mUP
pColWanted
pCAT
pUP
101
1
2
one
1
null
101
1
2
two
1
2
And it doesn't work as expected. It should return only one row with pColWanted = 'two', but returns two rows. If a specific row (with UP) exist in the mapping table, it shouldn't return the more generic row (without UP).
An empty string or NULL in the MappingTable is considered matching any value.
select m.PkId, p.ColWanted
from MainTable m
left join MappingTable p on (m.CAT = p.CAT or p.CAT is null or p.CAT ='' )
and (m.UP = p.UP or p.UP is null or p.UP ='')
Here's another solution:
SELECT m.PkId, p.ColWanted
FROM MainTable m
JOIN MappingTable p ON m.CAT = p.CAT AND m.UP = COALESCE(p.UP, m.UP)
Obvious m.UP = m.UP is guaranteed to be true. So when p.UP is NULL, the default is that the match is true.
Suppose I want select the matches with the MAX gameweek if the status of all matches is setted to 3, or the matches with MIN gameweek how can I do this?
Data sample
id | status | gameweek | round_id
1 3 3 1
2 3 3 1
3 1 3 1
4 1 4 1
5 1 4 1
6 1 4 1
the final result should be: 1, 2, 3 because not all the match has played.
I was able to setup a query for MAX:
SELECT MAX(gameweek) FROM `match` m WHERE round_id = 1 AND m.status = 3
but I have some difficult to implement an IF condition, someone could help me?
Thanks.
UPDATE
In the solution proposed by the users I noticed that I doesn't explain well a particular situation: if all the matches of a round doesn't have the status 3, the query should return the MIN(gameweek) of the round_id specified.
If I get this right, you could use a CASE. If a record with a status other than 3 exists return the minumum gameweek, else the maximum. Compare the result to the gameweek.
SELECT `m1`.*
FROM `match` `m1`
WHERE `m1`.`round_id` = 1
AND `m1`.`gameweek` = CASE
WHEN EXISTS (SELECT *
FROM `match` `m2`
WHERE `m2`.`round_id` = `m1`.`round_id`
AND `m2`.`status` <> 3) THEN
(SELECT min(`m3`.`gameweek`)
FROM `match` `m3`
WHERE `m3`.`round_id` = `m1`.`round_id`)
ELSE
(SELECT max(`m4`.`gameweek`)
FROM `match` `m4`
WHERE `m4`.`round_id` = `m1`.`round_id`)
END;
I'm not sure if you wanted to limit it to a certain round_id. It's in your query but not in the text. If you don't want it, remove all the conditions related to round_id.
Edit:
To use the maximum gameweek if not all status of a round are equal to 3 and the minimum gameweek otherwise you can check if the minimum of the status equals the maximum (i.e. all status are the same) and if it is equal to 3.
SELECT `m1`.*
FROM `match` `m1`
WHERE `m1`.`round_id` = 1
AND `m1`.`gameweek` = CASE
WHEN EXISTS (SELECT min(`m2`.`status`)
FROM `match` `m2`
WHERE `m2`.`round_id` = `m1`.`round_id`
HAVING min(`m2`.`status`) <> max(`m2`.`status`)
OR min(`m2`.`status`) <> 3) THEN
(SELECT min(`m3`.`gameweek`)
FROM `match` `m3`
WHERE `m3`.`round_id` = `m1`.`round_id`)
ELSE
(SELECT max(`m4`.`gameweek`)
FROM `match` `m4`
WHERE `m4`.`round_id` = `m1`.`round_id`)
END;
Assuming there can be more than one round_id:
SELECT *
FROM `match` m
WHERE (gameweek, round_id ) =
(
SELECT MAX(gameweek),round_id
FROM `match` m
WHERE round_id = 1 AND m.status = 3
GROUP BY round_id
)
DBFiddle DEMO
ok, simpler than I imagined, I discovered that I can achieve this target using the COALESCE operator, so:
m.gameweek = (SELECT COALESCE(MIN(
CASE WHEN m2.status < 3
THEN m2.gameweek END),
MAX(m2.gameweek))
FROM `match` m2
WHERE m2.round_id = m.round_id)
I have table data like
value pvalue value_type
an1001 bk1001 1
an1002 null 1
an1003 null 1
an1004 bk1002 1
bk1001 ck1001 2
bk1002 ck1002 2
ck1001 MG1001 3
ck1002 null 3
I m expecting result like
value pvalue1 pvalue2 pvalue2
an1001 bk1001 ck1001 MG1001
an1002 bk1002 ck1002
an1003
an1004
is there any way to write queries where i can avoid left outer join or inner join rather that i can use inline queires
You can use something like the following query. Please mind the syntax errors, if any.
select value,
max(case when value_type = 1 then pvalue else null end) as pvalue1,
max(case when value_type = 2 then pvalue else null end) as pvalue2,
max(case when value_type = 3 then pvalue else null end) as pvalue3
from table
group by value;
In the following query I'm doing the join of a table calendar and a second table where I need to specify some parameters to the query.
The join of the tables is performed on the field calendar.datefield and store_product.created
The problem is that I'm filtering by id_store = 3 and another row in 07/20/2012 store_product table record has id_store = 4 and thus the query does not bring the result. Is there any way to show this result as NULL, forcing mysql to ignore this case?
Result: (the row containing the date 2012-07-20 is not being displayed because it has other id_store)
DATE price
2012-07-17 NULL
2012-07-18 700.00
2012-07-19 NULL
2012-07-21 NULL
2012-07-22 NULL
2012-07-23 NULL
I would like to display
DATE price
2012-07-17 NULL
2012-07-18 700.00
2012-07-19 NULL
->>> 2012-07-20 NULL
2012-07-21 NULL
2012-07-22 NULL
2012-07-23 NULL
The query:
set #id_store = 3;
set #id_product = 11;
SELECT
calendar.datefield as DATE,
t1.price
FROM
store_product t1
RIGHT JOIN
calendar ON (DATE(t1.created) = calendar.datefield)
WHERE
(calendar.datefield BETWEEN ('2012-07-17') and ('2012-07-23'))
AND (t1.id_store = #id_store OR t1.id_store is NULL)
AND (t1.id_product = #id_product OR t1.id_product is NULL)
AND (t1.created = (select
max(f2.created)
from
store_product f2
where
f2.id_store = t1.id_store
and f2.id_product = t1.id_product
and DATE(t1.created) = DATE(f2.created))
OR t1.created is NULL)
GROUP BY DATE , t1.id_store , t1.id_product
That record cannot be displayed (obviously) because you are filtering out stores only with ID of 3. The RIGHT JOIN does what it's supposed to do, then then you're further reducing results with the filter. I think you'll have to handle this in your main code to add the "missing" records for you. I don't think SQL can do what you want it to do.
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.