I have a very simple static table:
type qty
A 10
B 20
C 30
I'd like to convert this table into one row result. I use this query:
SELECT type,
CASE WHEN type = 'A' THEN qty END AS 'A',
CASE WHEN type = 'B' THEN qty END AS 'B',
CASE WHEN type = 'C' THEN qty END AS 'C'
FROM mytable
GROUP BY type
The result is:
type A B C
A 10 NULL NULL
B NULL 20 NULL
C NULL NULL 30
my desired output:
A B C
10 20 30
You need to have one more column to transpose this using max() or sum() and group by. If you are grouping by Type, we get separate sets for each of 'A', 'B' and 'C', so we see separate rows.
example:
id Type Quantity
1 A 10
1 B 20
1 C 30
The query below would work with both MySQL 5.7(ONLY_FULL_GROUP_BY mode) and 5.6 as well. (Tested with v5.7.18 default settings.)
SELECT
MAX(CASE
WHEN Type = 'A' THEN qty
ELSE NULL
END) AS A,
MAX(CASE
WHEN Type = 'B' THEN qty
ELSE NULL
END) AS B,
MAX(CASE
WHEN Type = 'C' THEN qty
ELSE NULL
END) AS C
FROM
myTable
GROUP BY id;
where as this one fails with MySQL 5.7(ONLY_FULL_GROUP_BY mode)
Select id, Type from MyTable group by id;
Related
Given a table with the following data
ID Value
1 A
1 B
1 C
1 D
2 A
2 C
3 A
I would like to build a query that returns which values are missing from the id set based on value A being present. It can be assumed an ID for 'A' is always present.
Result:
ID | B | C | D
2 | 0 | 1 | 0
3 | 0 | 0 | 0
The values are A, B, C, D. In this example all values are there for ID 1 but the table reports that B is missing for both given that A is a value for ID 2 and so on.
I have a query to return which ID's are missing for a given value but I have not found a way to join all three together:
select id
from table_1
where id not in (
select id
from table_1
where value = 'B' #additional queries replacing 'B' with 'C' and 'D'
) and value = 'A'
order by id asc
Is it possible to combine those three separate queries in to a result table as I have laid out? I feel like this requires inner joins but have not been able to build out a query that works.
You could use conditional aggregation:
SELECT id,
SUM(Value = 'A') AS a,
SUM(Value = 'B') AS b,
SUM(Value = 'C') AS c,
SUM(Value = 'D') AS d
FROM tab
GROUP BY id;
DBFiddle Demo
Values list (A,B,C,D) has to be known in advance.
Skipping row if all values are present:
SELECT *
FROM (
SELECT id, SUM(Value = 'A') AS a,
SUM(Value = 'B') AS b,
SUM(Value = 'C') AS c,
SUM(Value = 'D') AS d
FROM tab
GROUP BY id
) sub
WHERE NOT (a>0 and b>0 and c>0 and d>0);
DBFiddle Demo2
I have two tables in mysql as below:
Table1 holds the questions
qid tid qtype
101 1 1
102 1 2
103 1 3
104 1 4
Here qtype is question type where qtype 1 and 2 accept numeric values and 3 and 4 accept string. I have declared qtype as varchar column.
Table2 holds the answers
sid qid qtype qanswer
1 101 1 10
1 102 2 20
1 103 3 o1
1 104 4 o2
there are rows for every question for every 'sid'.
I have selected data in below fashion using following query:
select a.sid, MAX(CASE WHEN (a.qid = 101) THEN if(a.qtype in(1,2),cast(a.qanswer as unsigned),a.qanswer) ELSE NULL END) AS '101' ,
MAX(CASE WHEN (a.qid = 102) THEN if(a.qtype in(1,2),cast(a.qanswer as unsigned),a.qanswer) ELSE NULL END) AS '102' ,
MAX(CASE WHEN (a.qid = 103) THEN if(a.qtype in(1,2),cast(a.qanswer as unsigned),a.qanswer) ELSE NULL END) AS '103' ,
MAX(CASE WHEN (a.qid = 104) THEN if(a.qtype in(1,2),cast(a.qanswer as unsigned),a.qanswer) ELSE NULL END) AS '104' from Table2 a join Table1 b on a.qtype = b.qtpe where b.tid = 1
sid 101 102 103 104
1 10 20 o1 o2
2 30 15 o2 o1
I wanted to select qtype 1 and 2 as integer so I used below statement in my query:
if(qtype in (1,2),cast(qanswer as unsigned),qanswer)
I am not getting answer for qtype 1 and 2 as desired.
I took reference from this question
I also tried convert instead of cast but got same result.
How can I cast qtype 1 and 2 as integer?
How to return integer value from mysql expression.
This is not a statement:
if(qtype in (1, 2), cast(qanswer as unsigned), qanswer)
This is an expression. An expression returns a scalar value with a single type. MySQL needs to decide if the returned type is unsigned or varchar, because it must choose one for the entire expression.
MySQL would appear to be choose the string type.
I have a table:
id flag
1 Y
1 Y
1 Y
1 N
1 N
2 Y
2 N
2 N
3 Y
3 N
i want to do as select statement which will give me the following output.
id count_flag_Y count_flag_N
1 3 2
2 1 2
3 1 1
I was trying using the select case method but getting syntax error.
SELECT id,SUM(CASE WHEN flag= 'Y') as count_flag_Y,
SUM(CASE WHEN flag= 'N') as count_flag_N
from tablename
GROUP BY id
Is there any way to do it?
Your query was not far off, you only have a slight problem with the CASE expressions. Try this:
SELECT id,
SUM(CASE WHEN flag= 'Y' THEN 1 ELSE 0 END) AS count_flag_Y,
SUM(CASE WHEN flag= 'N' THEN 1 ELSE 0 END) AS count_flag_N
FROM tablename
GROUP BY id
You are very close, but in MySQL the CASE is not needed:
SELECT id, SUM(flag = 'Y') as count_flag_Y,
SUM(flag = 'N') as count_flag_N
FROM tablename
GROUP BY id;
MySQL treats boolean expressions like integers in a numeric context, with "1" for true and "0" for false.
t_no name value
1 a 45
1 b 23
1 c 5
1 a 12
1 b 99
1 c 6
I need to show my above table as
no name value1 value2
1 a 45 12
1 b 23 99
1 c 5 6
You can't create dynamic columns in mysql alone, either in scripting language, or you can use group_concat to have them in one column:
SELECT to_no, name, GROUP_CONCAT(value)
FROM table GROUP BY to_no, name
result:
no name value
1 a 45,12
1 b 23,99
1 c 5,6
MySQL does not have a pivot function, but you can use an aggregate function with a CASE expression. Since you have multiple values for each t_no and name, then you could use user defined variables to assign a row number to each group of values:
select t_no, name,
max(case when rn=1 then value end) value1,
max(case when rn=2 then value end) value2
from
(
select t_no, name, value,
#rn:=case when #prev=t_no and #c=name then #rn else 0 end +1 rn,
#prev:=t_no,
#c:=name
from yourtable
cross join (select #rn:=0, #prev:=0, #c:=null) c
order by t_no, name
) d
group by t_no, name
order by t_no, name;
See SQL Fiddle with Demo
I've got a query that produces the right result, its just very slow. I feel like there must be a better way (perhaps without subqueries).
Table, result and query are below. I've anonymized the data and I have 8 subqueries rather than 2, but the format is the same.
Table "a":
id userId type amount
------------------------------------
1 1 a 400
2 1 b 300
3 1 c 230
4 2 a 600
5 2 b 500
6 2 c 430
I've got an index on each column and one additional one that encompasses the userId and type columns. I can also guarantee you that userId and type are unique (i.e. there would't be two type 'a' for user 1).
Desired Result:
userId typeAtotal typeBtotal
--------------------------------
1 400 300
2 600 500
My Query:
SELECT userId,
(SELECT amount
FROM a AS a2
WHERE a2.userId = a1.userId
AND a2.type = 'a') AS aAmt,
(SELECT amount
FROM a AS a3
WHERE a3.userId = a1.userId
AND a3.type = 'b') AS bAmt
FROM a AS a1
WHERE type IN ('a','b')
GROUP BY userId
Use:
SELECT t.userid,
MAX(CASE WHEN t.type = 'a' THEN amount ELSE NULL END) AS typeAtotal,
MAX(CASE WHEN t.type = 'b' THEN amount ELSE NULL END) AS typeBtotal
FROM YOUR_TABLE t
GROUP BY t.userid
If there can be more than one amount for either type - this will return the highest. If you want such situations added, use SUM:
SELECT t.userid,
SUM(CASE WHEN t.type = 'a' THEN amount ELSE NULL END) AS typeAtotal,
SUM(CASE WHEN t.type = 'b' THEN amount ELSE NULL END) AS typeBtotal
FROM YOUR_TABLE t
GROUP BY t.userid
Looks like cross-tabulation to me. You might try something like this:
SELECT userId,
SUM(IF(a.type = 'a'), a.amount, 0) AS aAmount,
SUM(IF(a.type = 'b'), a.amount, 0) AS bAmount
FROM a
WHERE type IN ('a', 'b')
GROUP BY a.userId
You might want to read this rather well-written tutorial: http://dev.mysql.com/tech-resources/articles/wizard/index.html
Edit: fixed the ELSE condition.