I have two tables where I need to return matching results on basis of CASE statement.
If the query returns data in the first case. We need to return data. We do not need to check the following case statements.
This is what I tried
Select
CASE
WHEN foo.Marks ='Two' AND t1.Subject = 3 THEN foo.UniqueValue
END as 'Result',
CASE
WHEN foo.Marks ='0' AND t1.Subject = 3 THEN foo.UniqueValue
END as 'Result1',
CASE
WHEN foo.Marks IS NULL AND t1.Subject IS NULL THEN foo.UniqueValue
END as 'Result2'
from (
select t1.Marks, t1.Subject, t1.Student, foo.UniqueValue from `table1` t1
inner join `table2` t2 on t1.Student = t2.GroupName
where t2.GroupID = 2
)foo;
id
Marks
Subject
Student
UniqueValue
1
Two
3
FOO
AIR1
2
0
3
FOO
AIR2
3
NULL
NULL
FOO
AIR3
id
GroupID
GroupName
1
2
FOO
2
3
BAR
3
7
FOO123
Level 1 -> If Marks and Subject matched it should return that AIR1.
Level 2 -> If Marks is 0 and Subject is 3 should return AIR2.
If both above cases do not find any result then the below case should be checked.
Level 3 -> If Marks is NULL and Subject is NULL should return AIR3
If in Level1, the matching row is found it should return that Level2,3 should not be checked.
In the final, I should only get a single row matching the above levels by priority.
If GroupID is known,
SELECT t1.UniqueValue
FROM table1 t1
JOIN table2 t2 ON t1.Student = t2.GroupName
WHERE t2.GroupID = 2
ORDER BY
CASE WHEN t1.Marks = 'Two' AND t1.Subject = 3 THEN 1
WHEN t1.Marks = '0' AND t1.Subject = 3 THEN 2
WHEN t1.Marks IS NULL AND t1.Subject IS NULL THEN 3
ELSE 4 END ASC
LIMIT 1
To get one result for each GroupID
WITH cte AS (
SELECT t1.UniqueValue, ROW_NUMBER() OVER(PARTITION BY t2.GroupID ORDER BY CASE WHEN t1.Marks = 'Two' AND t1.Subject = 3 THEN 1
WHEN t1.Marks = '0' AND t1.Subject = 3 THEN 2
WHEN t1.Marks IS NULL AND t1.Subject IS NULL THEN 3
ELSE 4 END ASC) rn
FROM table1 t1
JOIN table2 t2 ON t1.Student = t2.GroupName
)
SELECT UniqueValue
FROM cte
WHERE rn = 1
Why don't you just do ELSE instead of END and new CASE?
Select
(CASE
WHEN foo.Marks ='Two' AND t1.Subject = 3 THEN foo.UniqueValue
ELSE
WHEN foo.Marks ='0' AND t1.Subject = 3 THEN foo.UniqueValue
ELSE
WHEN foo.Marks IS NULL AND t1.Subject IS NULL THEN foo.UniqueValue
END) Result
from (
select t1.Marks, t1.Subject, t1.Student, foo.UniqueValue from `table1` t1
inner join `table2` t2 on t1.Student = t2.GroupName
where t2.GroupID = 2
)foo;
Related
I have 2 tables with stock from two different sellers.
If I can not source the product from any of these two sellers then I would like to set a value in another table to '0'.
First of all I am getting some required values from the two seller stock tables combined with a UNION
(SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'Stock available' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_dm` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '1' AND B.`product_id` > '0'
UNION
SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'In Stock' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_m` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '2' AND B.`product_id` > '0') t1
If I get a result like below where in_stock = 0 for both sellers then I would like to update another field with 0
id product_id internal_id in_stock
1 123 5555 0
1 123 4567 0
If I can source the product from one (like below) or both sellers then I don't want to do anything.
id product_id internal_id in_stock
1 123 5555 0
1 123 4567 1
Basically how can I check if all results for a product_id are 'in_stock = 0' and based on that do an update of another table.
Thank you
There are easier ways to do this if the tables can be joined, but You could get the max in_stock number and knowing that if it's over 0 you could do it with a CTE like this (I am not able to test this in mysql so it may need some syntax correction)
WITH CTE (in_stock) AS (
SELECT MAX(in_stock) from (
(SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'Stock available' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_dm` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '1' AND B.`product_id` > '0'
UNION
SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'In Stock' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_m` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '2' AND B.`product_id` > '0') t1 ))
UPDATE some_table SET some_column = 0
where CTE.in_stock < 1
I used nested queries and a variable to meet your criteria.
See example DDL in this link:https://www.db-fiddle.com/f/8jUMnbEFpGWA4fmmP67yw9/0 I think this meets your requirements.
Here is my Query, with comments:
#check initial another table values
select * from another_table;
#check the given resultset
#there are 3 pairs,
#2 of which meet the condition for not updating
#1 of the pairs meets the condition for doing the requested update
SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'Stock available' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_dm` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '1' AND B.`product_id` > '0'
UNION
SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'In Stock' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_m` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '2' AND B.`product_id` > '0';
#the requested update statement
set #chk1 := 0;
update another_table
set crab_people = 0
where product_id in
#this nested query will return all product_id
#that fits the criteria to update another_table
(select product_id_not_in_stock from
(select
case
when product_id = #chk1 and in_stock = 0 then #chk1
when product_id != #chk1 and in_stock = 0 then #chk1 := product_id
end as product_id_not_in_stock
from
(SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'Stock available' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_dm` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '1' AND B.`product_id` > '0'
UNION
SELECT A.`id`, B.`product_id`, A.`internal_id`, CASE WHEN A.`in_stock` = 'In Stock' THEN '1' ELSE '0' END as `in_stock` FROM `pricing_m` A LEFT JOIN `pricing_vendor_mapping` B ON A.`internal_id`= B.`internal_id` WHERE B.`vendor_id` = '2' AND B.`product_id` > '0') as t1
order by product_id, in_stock DESC, internal_id) as t2
where product_id_not_in_stock is not null
group by product_id_not_in_stock
having count(product_id_not_in_stock) > 1);
#confirm the changes went though
#expect crab_people from another_table to be updated
#where the product id is not in stock from both tables: pricing_dm and pricing_m
select * from another_table;
I have a set of one to one mappings A -> apple, B-> Banana and like that.. My table has a column with values as A,B,C..
Now I'm trying to use a select statement which will give me the direct result
SELECT T1.job, T1.pid, T2.T2MAX, T1.message, T1.duration, T1.T1SUM ,'message' As message ,
CASE WHEN T1.T1SUM = 0 THEN 'yellow' WHEN T1.T1SUM > 0 THEN 'green' ELSE NULL END AS color
FROM(SELECT monitor.statcatcher.job,monitor.statcatcher.pid, MIN(monitor.statcatcher.moment)AS T1MIN, monitor.statcatcher.message,monitor.statcatcher.duration,
SUM(Coalesce(monitor.flowmetercatcher.count, 0)) AS T1SUM
FROM monitor.statcatcher
LEFT JOIN monitor.flowmetercatcher ON monitor.statcatcher.pid = monitor.flowmetercatcher.pid AND DATE(monitor.statcatcher.moment) =
DATE(monitor.flowmetercatcher.moment)
WHERE DATE(monitor.statcatcher.moment) = CURRENT_DATE AND message IS NOT NULL
GROUP BY monitor.statcatcher.job,monitor.statcatcher.pid, monitor.statcatcher.message, monitor.statcatcher.duration)AS T1
INNER JOIN(SELECT monitor.statcatcher.job,MAX(monitor.statcatcher.moment) AS T2MAX,
monitor.statcatcher.pid
FROM monitor.statcatcher
WHERE DATE(monitor.statcatcher.moment) = CURRENT_DATE
GROUP BY monitor.statcatcher.job) AS T2
ON T1.job = T2.job AND T1.pid = T2.pid
I have a table like this:
score
id week status
1 1 0
2 1 1
3 1 0
4 1 0
1 2 0
2 2 1
3 2 0
4 2 0
1 3 1
2 3 1
3 3 1
4 3 0
I want to get all the id's of people who have a status of zero for all weeks except for week 3. something like this:
Result:
result:
id w1.status w2.status w3.status
1 0 0 1
3 0 0 1
I have this query, but it is terribly inefficient on larger datasets.
SELECT w1.id, w1.status, w2.status, w3.status
FROM
(SELECT s.id, s.status
FROM score s
WHERE s.week = 1) w1
LEFT JOIN
(SELECT s.id, s.status
FROM score s
WHERE s.week = 2) w2 ON w1.id=w2.id
LEFT JOIN
(SELECT s.id, s.status
FROM score s
WHERE s.week = 3) w3 ON w1.id=w3.id
WHERE w1.status=0 AND w2.status=0 AND w3.status=1
I am looking for a more efficient way to calculate the above.
select id
from score
where week in (1, 2, 3)
group by id
having sum(
case
when week in (1, 2) and status = 0 then 1
when week = 3 and status = 1 then 1
else 0
end
) = 3
Or more generically...
select id
from score
group by id
having
sum(case when status = 0 then 1 else 0 end) = count(*) - 1
and min(case when status = 1 then week else null end) = max(week)
You can do using not exists as
select
t1.id,
'0' as `w1_status` ,
'0' as `w2_status`,
'1' as `w3_status`
from score t1
where
t1.week = 3
and t1.status = 1
and not exists(
select 1 from score t2
where t1.id = t2.id and t1.week <> t2.week and t2.status = 1
);
For better performance you can add index in the table as
alter table score add index week_status_idx (week,status);
In case of static number of weeks (1-3), group_concat may be used as a hack..
Concept:
SELECT
id,
group_concat(status) as totalStatus
/*(w1,w2=0,w3=1 always!)*/
FROM
tableName
WHERE
totalStatus = '(0,0,1)' /* w1=0,w2=1,w3=1 */
GROUP BY
id
ORDER BY
week ASC
(Written on the go. Not tested)
SELECT p1.id, p1.status, p2.status, p3.status
FROM score p1
JOIN score p2 ON p1.id = p2.id
JOIN score p3 ON p2.id = p3.id
WHERE p1.week = 1
AND p1.status = 0
AND p2.week = 2
AND p2.status = 0
AND p3.week = 3
AND p3.status = 1
Try this, should work
Need to check in where case that if not found where type='P' then it take record of type='C'
here is table
paper_id | product_id | type
1 1 P
2 1 P
3 1 C
4 1 C
5 2 C
6 2 C
There is product_id 1 and 2, need to get those record that have type='P' but those product who have not type='P' the record get from record type='C'
after query need this result
paper_id | product_id | type
1 1 P
2 1 P
5 2 C
6 2 C
i try
select * from table where CASE WHEN type !='P' THEN type='C' ELSE type='P'END
but not working
select paper_id, product_id, type from your_tab
where type = 'P'
union all
select t1.paper_id, t1.product_id, t1.type from your_tab t1
where t1.type = 'C'
and not exists (select 1 from your_tab t2
where t2.product_id = t1.product_id and t2.type = 'P');
maybe this will help
SELECT DISTINCT T.PRODUCT_ID, T.PAPER_ID, T.TYPE
FROM YOUR_TABLE T
WHERE (CASE
WHEN T.TYPE = 'P' THEN
'TRUE'
WHEN T.TYPE != 'P' THEN
(CASE
WHEN (SELECT COUNT(*)
FROM YOUR_TABLE T2
WHERE T2.PRODUCT_ID = T.PRODUCT_ID
AND T2.TYPE = 'P') = 0 THEN
'TRUE'
ELSE
'FALSE'
END)
END) = 'TRUE'
I'm facing to very hard pb, i don"t find the way to achieve this, i want count how many occurence is equal to member1(id1) 's occurence , as you see here ,
id2 have 4 equal occurence of id1 and id3 have only 1 egual occurence:
my table test is :
id classement aptitude A B C
1 2440 oui 2 9 1
2 2440 oui 2 9 5
3 1760 oui 1 8 5
4 2440 oui 2 9 1
In this exemple ,result expeted should be :
id count
4 5
2 4
3 1
Whats kind of query could achieve it please, is it possible ?!
Try:
select T2.id,
coalesce((T1.classement=T2.classement),0)+
coalesce((T1.aptitude=T2.aptitude),0)+
coalesce((T1.A=T2.A),0)+
coalesce((T1.B=T2.B),0)+
coalesce((T1.C=T2.C),0) match_count
from Temp T1
cross join Temp T2
where T1.id = 1 and T2.id <> 1
order by 2 desc
SQLFiddle here.
Here is the Working DEMO of SQLFiddel
Below is the Sample Query
select T1.id,
(Case T1.classement
when T2.classement Then 1 Else 0
End)+
(Case T1.aptitude
when T2.aptitude Then 1 Else 0
End)+
(Case T1.A
when T2.A Then 1 Else 0
End)+
(Case T1.B
when T2.B Then 1 Else 0
End)+
(Case T1.C
when T2.C Then 1 Else 0
End) Count
from Temp T1,
(select *
from Temp
where id =1) T2
where T1.id <> 1
and (T1.classement = T2.classement
or T1.aptitude = T2.aptitude
or T1.A = T2.A
or T1.B = T2.B
or T1.C =T2.C)
order by 2 desc
This might work:
select a.id,
length((case when a.aptitude = b.aptitude then '1' else '' end) ||
(case when a.classement = b.classement then '1' else '' end) ||
(case when a.A = b.A then '1' else '' end) ||
(case when a.B = b.B then '1' else '' end) ||
(case when a.C = b.C then '1' else '' end)) count
from test a,
(select *
from test
where id = 1) b
where a.id != 1