is this query COUNT is impossible? - mysql

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

Related

Mysql case if result found in first case do not run next

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;

mysql - why condition where is not work?

SELECT
t1.user_id,
count(*) total,
sum(case when t1.var1 = 'yes' then 1 else 0 end) as type1,
sum(case when t1.var1 = 'no' then 1 else 0 end) as type2
FROM table as t1
WHERE type1 > 0
GROUP by t1.user_id
ORDER by type1 DESC
LIMIT 100
In result i get rows:
user_id total type1 type2
1 100 80 20
4 120 70 50
6 90 0 90
Tell me please why condition WHERE type1 > 0 not work and how select rows with this condition ?
The WHERE only works on the original value and not on a variable you just made by summing the other values up, you can use HAVING for this:
SELECT
t1.user_id,
count(*) total,
sum(case when t1.var1 = 'yes' then 1 else 0 end) as type1,
sum(case when t1.var1 = 'no' then 1 else 0 end) as type2
FROM table as t1
GROUP by t1.user_id
HAVING type1 > 0
ORDER by type1 DESC
LIMIT 100
See here for another example of using HAVING: http://www.w3schools.com/sql/sql_having.asp

Slow SQL query return - How to get better results?

I’ve been asked to write a query that returns accounts with only specific action codes (internal name). There are 6 codes that have to be on the account and no other codes can be on. The table is stored in a table called tblTrans (see below) :
AccountNo ActionCode TransactionNo
1234 Code1 45646453
1234 Code2 88758475
1234 Code3 48978978
1234 Code4 15687898
1234 Code5 59878988
1234 Code6 12345677
2548 Code1 45464533
2548 Code2 89789489
2548 Code3 89789781
2548 Code4 16878983
2548 Code5 59889884
2548 Code6 12456776
2548 Code12 12348887
So the desired output would only return account 1234.
Currently this is being done with a query like
SELECT AccountNo, ActionCode, TransactionNo
FROM tblTrans AS t1
INNER JOIN
tblTrans AS t2 ON t1.AccountNo = t2.AccountNo
tblTrans AS t3 ON t2.AccountNo = t3.AccountNo
tblTrans AS t4 ON t3.AccountNo = t4.AccountNo
tblTrans AS t5 ON t4.AccountNo = t5.AccountNo
tblTrans AS t6 ON t5.AccountNo = t6.AccountNo
WHERE t1.ActionCode = 'Code1'
AND t2.ActionCode = 'Code2'
AND t3.ActionCode = 'Code3'
AND t4.ActionCode = 'Code4'
AND t5.ActionCode = 'Code5'
AND t5.ActionCode = 'Code6'
AND t6.AccountNo NOT IN (SELECT ActionCode
FROM tblTrans
WHERE ActionCode IN ('Code12'))
Sorry if the syntax is out I have had to change a few details for security reasons!
This actually runs very slowly and chokes the system up little. My question is, is there a better way to write this type of query. I don’t know much about CTE’s but sounds like it would fit?
This should return AccountNo's where there is ONLY your desired codes.
SELECT AccountNo
FROM tblTrans
GROUP BY AccountNo
HAVING Sum(Case When ActionCode = 'Code1' Then 1 End) > 0
And Sum(Case When ActionCode = 'Code2' Then 1 End) > 0
And Sum(Case When ActionCode = 'Code3' Then 1 End) > 0
And Sum(Case When ActionCode = 'Code4' Then 1 End) > 0
And Sum(Case When ActionCode = 'Code5' Then 1 End) > 0
And Sum(Case When ActionCode = 'Code6' Then 1 End) > 0
And Sum(Case When ActionCode IN ('Code1', 'Code2', 'Code3', 'Code4', 'Code5', 'Code6') Then 0 Else 1 End) = 0
I modified the query. This one should perform better. If the performance is still not acceptable, then you should probably consider adding an index to your table.
To return all the data...
; With FilteredData As
(
SELECT AccountNo
FROM tblTrans
GROUP BY AccountNo
HAVING Sum(Case When ActionCode = 'Code1' Then 1 End) > 0
And Sum(Case When ActionCode = 'Code2' Then 1 End) > 0
And Sum(Case When ActionCode = 'Code3' Then 1 End) > 0
And Sum(Case When ActionCode = 'Code4' Then 1 End) > 0
And Sum(Case When ActionCode = 'Code5' Then 1 End) > 0
And Sum(Case When ActionCode = 'Code6' Then 1 End) > 0
And Sum(Case When ActionCode IN ('Code1', 'Code2', 'Code3', 'Code4', 'Code5', 'Code6') Then 0 Else 1 End) = 0
)
Select TblTrans.AccountNo, ActionCode, TransactionNumber
From TblTrans
Inner Join FilteredData
On tblTrans.AccountNo = FilteredData.AccountNo

Complex querying on table with multiple userids

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

If not found in record then get other where case in mysql

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'