mysql case statement for counting - mysql

Table t1
col1 col2 col3
---- ---- ----
1 cat 2
2 dog 3
3 cat 4
4 dog 5
Table t2
id type
---- ----
1 a
2 a
3 b
4 b
I want to transform it such that it becomes this:
col2 a b
---- ---- ----
cat 2 4
dog 3 5
Query
Select t1.col2,
case when t2.type = 'a' then count(t1.col3) end as a,
case when t2.ab = 'b' then count(t1.col3) end as b
From mytable t1 join mytable2 t2 on t1.col1=t2.id where t1.col3 is not null
group by 1;
It populates only a or b column.
What is wrong with my query?

You need to move the case statement into the count() (or sum()) itself:
Select t1.col2,
count(case when t2.type = 'a' then 1 else null end) as a,
count(case when t2.type = 'b' then 1 else null end) as b
From mytable t1 join mytable2 t2 on t1.col1=t2.id where t1.col3 is not null
group by 1;

Related

Using CASE in Mysql to set value to an Alias field

I have 2 tables in Mysql which looks as follows
Table 1
ID YEARMONTH
------------------
1 201210
2 201211
3 201212
Table2
ID YEARMONTH GRADE DESIG
--------------------------------
1 201210 G1 NULL
2 201210 G1 D2
3 201212 G1 D1
I am trying to set a new field (named FLAG) in table1 which will be Y if rows exist for t1.YEARMONTH in T2 else N
I want the following Result in T1
ID YEARMONTH FLAG
---------------------
1 201210 Y
2 201211 N
3 201212 Y
I have tried the following Query
SELECT
T1.ID,
T1.YEARMONTH,
CASE COUNT(T2.ID)
WHEN (SELECT
COUNT(T2.ID)
FROM TABLE2 T2)
> 0 THEN 'Y'
ELSE 'N'
END AS flag
FROM TABLE1 T1,
table2 T2;
But it produces the following output
ID YEARMONTH FLAG
---------------------------
1 201210 N
I don't know where my mistake lies. Any help would be appreciated.
Try using the below query:
SELECT
T1.ID, T1.YEARMONTH,
(CASE
WHEN COUNT(T2.ID) > 0 THEN 'Y'
ELSE 'N'
END) AS FLAG
FROM TABLE1 T1
LEFT JOIN TABLE2 T2
ON T1.YEARMONTH = T2.YEARMONTH
GROUP BY T1.ID, T1.YEARMONTH
You can see the required output here http://sqlfiddle.com/#!9/162855/12
TRY THIS: Using CASE with LEFT JOIN you can check the existence of t1.yearmonth in t2.yearmonth and generate the flag column accordingly
SELECT DISTINCT t1.id,
t1.yearmonth,
(CASE WHEN t2.yearmonth IS NOT NULL THEN 'y' ELSE 'n' END) flag
FROM table1 t1
LEFT JOIN table2 t2 ON t1.yearmonth = t2.yearmonth

Mixing 3 sql queries in 1

I have 3 tables as follows
Table1
Id Name
1 abcd
2 bcd
3 dabc
Table2
Id2 Name2
2 xyz
3 def
4 mno
Table3
Id Id2 Value
1 4 1
2 3 1
3 4 1
Now,
From table1 : I have to select all Id where Name is %abc%
From table2: I have to select Id2 where Name2 is "mno"
From Table3: I have to change value to 0 from 1 where Id's value are from Table1 and Id2 is from Table2.
Table 1:
select Id from Table1 where Name like '%abc%'
Table2 :
select Id2 from Table2 where Name2 = "mno"
Table 3:
update Table3 set Value = 0 where Id in() and Id2=
But, I dont know how to make it 1 single query. Can anyone please guide me up ?
Refer to: prior stack article
You've not explained how T1 relates to T2, So I have assumed a cross join.
Whenever you have a record in T1 with name like '%abc%' (1,3) in your data..
and whenever you have a record in T2 with a name equal to 'mno' 4 then you want the value in table 3 to be 0
so the select we generate should produce
1,4
3,4
and when we inner join this back to table 3 it only selects
Id Id2 Value
1 4 1
3 4 1
Now we generate an update based on this select as outlined in the link provided above...
UPDATE table3
INNER JOIN (
SSELECT t1.ID t1ID, t2.id t2ID
FROM table1 t1
CROSS JOIN table2
WHERE t1.name like '%abc%'
and t2.name like = 'mno') B
on B.t1ID = t3.Id
and B.t2ID = T3.ID2
SET value = 0
Giving us a result of
Id Id2 Value
1 4 0
2 3 1
3 4 0
if we select * from table3
update t3
set t3.Value = 0
from Table3 t3
inner join Table1 t1
on t3.Id = t1.Id
inner join Table2 t2
on t3.Id2 = t2.Id2
where t1.Name like '%abc%' and t2.Name2 = 'mno'
OR
update Table3
set value = 0
where Id in (select Id from Table1 where Name like '%abc%')
and Id2 in (select Id2 from Table2 where Name2 = 'mno')
You should think about UPDATE ... WHERE EXISTS as follows:
update Table3 set Value = 0
WHERE EXISTS (SELECT 1 FROM Table1 where Name LIKE '%abc%' AND Table1.Id=Table3.Id )
AND EXISTS (SELECT 1 FROM Table2 where Name2 = "mno" AND Table2.Id2=Table3.Id2)

select a field values that are not found in another table

I need a query which should results a fields that are not found in another table. Let say,
table 1:
comp col1 col2 col3 col4
----------------------------------
nam1 1 1 b c
nam2 0 0 abc c
nam3 1 1 a c
nam4 1 1 b c
nam5 0 0 c c
table2:
name col1 col2
----------------------
b 3 f
a 4 f
c 5 f
result:
comp col3 col4
----------------------
nam2 abc c
the result be based on col3,col1=0,col2=0 on first table and name in second table..abc is not found in table2...
thanks in advance.
The question is not very clear, but if I understood you correctly, you want to select all rows from table1 where col1 and col2 are both 0, and col3 is not contained in the name column of table2. If so, your query should be simple enough:
SELECT comp, col3, col4
FROM table1
WHERE col1 = 0
AND col2 = 0
AND col3 NOT IN (SELECT name FROM table2);
As per the explanation the joining key between table1 and table2 is
table1.col3 = table2.name
Using this you can use the following query
select
t1.comp,
t1.col3,
t1.col4
from table1 t1
left join table2 t2 on t2.name = t1.col3
where t2.name is null

Show only differences between two rows in mysql

Having a (MySQL) audit table containing rows that are similar, is it possible to view only those columns that have different values?
For example, a table containing four columns where column key is primary key, and column id is the identifier to match rows:
key id col1 col2
1 123 B C
2 123 A C
3 456 B C
4 789 B A
5 789 B B
6 987 A C
In the example above I need the query to return only row 1, 2, 4, and 5 as they have matching id, and differing values in col1 and col2, ie B,A and B,A.
key id col1 col2
1 123 B
2 123 A
4 789 A
5 789 B
I know it might not be very efficient solution, but gives what you want. HERE try this:
SELECT A.ID, (CASE A.col1 WHEN B.col1 THEN NULL ELSE B.col1 END), (CASE A.col2 WHEN B.col2 THEN NULL ELSE B.col2 END) FROM tblName A
FULL OUTER JOIN tblName B
ON
A.ID=B.ID
WHERE
(A.col1=B.col1 AND A.Col2<>B.Col2)
OR
(A.col2<>B.col2 AND A.Col1=B.Col1)
INNER JOIN should give same result
This is a bit contrived, in the sense that adding more rows will give very different results - but anyway...
SELECT x.my_key
, x.id
, IF(y.col1=x.col1,'',x.col1) col1
, IF(y.col2=x.col2,'',x.col2) col2
FROM my_table x
JOIN my_table y
ON y.id = x.id
AND y.my_key <> x.my_key
WHERE (y.col1 <> x.col1 OR y.col2 <> x.col2)
ORDER
BY my_key;
Thanks for all responses which guided me.
Using your suggestions I made the sql like this:
SELECT
T1.KEY,
T1.ID,
CASE T2.COL1_DISTINCT_VALUES WHEN 1 THEN NULL ELSE T1.COL1 END AS COL1,
CASE T2.COL2_DISTINCT_VALUES WHEN 1 THEN NULL ELSE T1.COL2 END AS COL2
FROM
TAB1 T1
INNER JOIN
(
SELECT
ID,
COUNT(DISTINCT COL1) AS COL1_DISTINCT_VALUES,
COUNT(DISTINCT COL2) AS COL2_DISTINCT_VALUES
FROM
TAB1
GROUP BY
ID
) T2
ON T1.ID=T2.ID
WHERE
T2.COL1_DISTINCT_VALUES > 1
OR T2.COL2_DISTINCT_VALUES > 1
ORDER BY
KEY,ID;

Complex query over two tables

I have two tables:
table1:
id
--
1
2
3
table2: (left out primary index)
id2 | cond
----------
3 | 1
3 | 0
2 | 1
2 | 1
2 | 0
I would need to construct a query that implicitly calculates this intermediary table:
temp:
id | c1 | c2
------------
1 | 0 | 2
2 | 2 | 2
3 | 1 | 2
with c1 = countRows(id2 == id && cone == 1) and c2 == countRows(id2 = 2 && cond == 1).
and then selects SELECT id FROM temp ORDER BY ABS(c1 - c2)*RAND().
My current try is kind of like:
SELECT id, COUNT(t1.id2) AS c1, COUNT(t2.id2) AS c2
FROM table1 LEFT JOIN (table2 AS t1) ON id=t1.id2 LEFT JOIN (table2 AS t2) ON t2.id2=2
WHERE t1.cond=1 AND t2.cond=1
GROUP BY t1.id2
ORDER BY ABS(c1 - c2)*RAND()
LIMIT 1
Which has multiple problems:
It doesn't select rows with no entry in table2
It doesn't correctly count
There seems to be a problem with group columns (c1, c2) in the ORDER BY part 3.
Help would be appreciated.
Update:
table1 represents players for example
table2 would be rounds played, with cond indicating a win
c1 represents the rounds won by each player
c2 represents the rounds won by a reference player (player 2 in this case)
SELECT t1.id, SUM(IFNULL(t2.cond, 0) = 1) AS c1, (SELECT SUM(cond = 1) FROM table2 WHERE id2 = 2) AS c2
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id2
GROUP BY t1.id
ORDER BY ABS(SUM(IFNULL(t2.cond, 0) = 1) - c2) * RAND();
Let's see if the first part of your query is returning valid results..
SELECT
t1.id AS id
COUNT(t2.id2) AS c1
COUNT(CASE WHEN t3.id2 = 2 THEN t3.id2 ELSE NULL END) as c2
FROM
table1 AS t1
LEFT JOIN table2 as t2
ON t1.id = t2.id2 AND t2.cond = 1
LEFT JOIN table2 as t3
ON t3.id2 = 2 AND t3.cond = 1
GROUP BY
t2.id2,
t3.id2
Can you provide schema?