MySQL-how to merge multiple rows into multiple columns and one row? - mysql

If I have a MySQL table looking something like this: for example 2014000 is a product pen , there are four types abcd with different prices. and 2014001 is another prodct telephone , also there three types efg with different prices. now I want to get the one product one line with names and values.
id code name value
1 2014000 A 10
2 2014000 B 9
3 2014000 C 11
4 2014000 D 12
5 2014001 E 100
6 2014001 F 110
7 2014001 G 120
respect result:
code name1 value1 name2 value2 name3 value3 name4 value4
----------- --------- --------- --------- --------- ----------- --------- --------- ---------
2014000 A 10 B 9 C 11 D 12
2014001 E 100 F 110 G 120 null null
CREATE TABLE T (ID INT, code INT, NAME CHAR(1), VALUE VARCHAR(10));
INSERT INTO T VALUES(1,2014000,'A','10'), (2,2014000,'B','9'), (3,2014000,'C','11'), (4,2014000,'D','12'), (5,2014001,'E','100'), (6,2014001,'F','110'), (7,2014001,'G','120');
-----the followed only for two rows , if there are more than four rows, how to do it?
SELECT T1.code, T2.name AS name1, T2.value AS value1, T3.name AS name2, T3.value AS value2 FROM( SELECT code,MIN(ID) AS ID1,CASE COUNT(code) WHEN 1 THEN NULL ELSE MAX(ID) END AS ID2 FROM T GROUP BY code ) T1 LEFT JOIN T T2 ON T1.ID1 = T2.ID LEFT JOIN T T3 ON T1.ID2 = T3.ID

SELECT t.code
, t1.name name1
, t1.value value1
, t2.name name2
, t2.value value2
, t3.name name3
, t3.value value3
, t4.name name4
, t4.value value4
FROM ( SELECT code
, group_concat(ID) ids
FROM T
GROUP BY code
) t
LEFT JOIN T t1
ON find_in_set(t1.ID,t.ids)=1
LEFT JOIN T t2
ON find_in_set(t2.ID,t.ids)=2
LEFT JOIN T t3
ON find_in_set(t3.ID,t.ids)=3
LEFT JOIN T t4
ON find_in_set(t4.ID,t.ids)=4

Related

Getting values from 2 tables with different conditions for both tables

Table 1
ID
FirstName
LastNmae
city
Group
code
11
john
smith
abc
E
P
21
don
davis
def
E
P
3
vee
miller
ghi
Q
P
6
vee
miller
ghi
Q
P
Table 2
ID
FirstName
LastNmae
city
Status
EmpName
Phone
11
john
smith
abc
U
Company 1
123
21
don
davis
def
P
Company 2
456
3
vee
miller
ghi
C
Company 3
789
4
jim
jones
xyz
P
comapany4
001
I have 2 tables mentioned above. I need an output from both table under these conditions
For table 1 condition is:
Group='E' AND code='P'
For table 2 condition is : Status = 'U' OR Status = 'P'
For output required columns are:
ID, FirstName, LastName, City, EmpName, Phone
I cannot use UNION because number of columns mismatch.
Desired Output:
ID
FirstName
LastNmae
city
EmpName
Phone
11
john
smith
abc
Company 1
123
21
don
davis
def
Company 2
456
4
jim
jones
xyz
comapany4
001
How can i get desired output. With UNION i can't get "EmpName" and "Phone" column. Is there anyway to use JOIN to get desired output.
I think you still need UNION. Try this query:
SELECT ID, FirstName, LastName, city, EmpName, Phone
FROM table2
WHERE Status IN ('U', 'P')
UNION
SELECT t1.ID, t1.FirstName, t1.LastName, t2.city, t2.EmpName, t2.Phone
FROM table1 AS t1
LEFT JOIN table2 AS t2 ON t1.ID = t2.ID
WHERE t1.Group = 'E' AND t1.code = 'P'
;
First, your results are all coming from table2, so this returns the results specified in the question:
select t2.ID, t2.FirstName, t2.LastName, t2.city, t2.EmpName, t2.Phone
from table2 t2
where t2.status in ('U', 'P');
I think you also want a matching condition on table1 (which is not needed for your example). Based on your description:
select t2.ID, t2.FirstName, t2.LastName, t2.city, t2.EmpName, t2.Phone
from table2 t2
where t2.status in ('U', 'P') or
exists (select 1
from table1 t1
where t1.id = t2.id and
t1.Group = 'E' and t1.code = 'P'
);

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)

MySQL merge two tables with different data

The following are my mysql tables
Table 1:
ID | commonID | Date | text | active
1 11 01.02 abc 1
2 11 02.02 123 1
3 11 03.02 xyz 0
Table 2:
ID | commonID | Date | value | active
1 11 01.02 abc 1
2 11 04.02 123 1
3 11 03.02 xyz 1
The Final result should display this:
| date | text | value
01.02 abc abc
02.02 123 (null)
03.02 (null) xyz
04.02 (null) 123
The Idea here is, to merge the two tables. All entries with a defined commonID like 11 in the example will be selected from both tables. then the tables will be united.
Conditions:
If there are matching dates in TABLE1 and TABLE2 they will be merged
If there is a solo date in TABLE1 or TABLE2, the value/text for the table with no date will become NULL
If there is a record in TABLE1 or TABLE2 that has active = FALSE, it will not be processed.
There can be matching and not matching dates in BOTH tables.
I want to use this for display chronologic events, if there is an event in both tables, there should be only one line for this.
What could be the Solution here?
Try this:
SELECT T1.date,
CASE WHEN T1.active = 1 THEN T1.text END as text,
CASE WHEN T2.active =1 THEN T2.value END as value
FROM Table1 T1 LEFT JOIN
Table2 T2 ON T1.date=T2.date
UNION
SELECT T2.date,
CASE WHEN T1.active = 1 THEN T1.text END as test,
CASE WHEN T2.active = 1 THEN T2.value END as value
FROM Table1 T1 RIGHT JOIN
Table2 T2 ON T1.date=T2.date
Result:
DATE TEXT VALUE
01.02 abc abc
02.02 123 (null)
03.02 (null) xyz
04.02 (null) 123
Sample SQL Fiddle.
Try this:
SELECT t1.date,t1.text,t2.value FROM table1 t1
LEFT JOIN table2 t2 ON t1.commonId = t2.commonId and t1.date = t2.date and t2.active = 1
where t1.active = 1
UNION
SELECT t2.date,t1.text,t2.value FROM table2 t2
LEFT JOIN table1 t1 ON t1.commonId = t2.commonId and t1.date = t2.date and t1.active = 1
where t2.active = 1
Sample http://sqlfiddle.com/#!2/d2c4d/2
Here's one way...
SELECT commonid
, date
, MAX(text) text
, MAX(value) value
FROM
( SELECT id
, commonid
, date
, text
, NULL value
, active
FROM table1
WHERE active <> 0
UNION
SELECT id
, commonid
, date
, NULL
, value
, active
FROM table2
WHERE active <> 0
) x
GROUP
BY commonid,date;
You can move the WHERE active <> 0 bit out of the UNIONs if you like, to just before the GROUP BY.

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?

Joining multiple lines from the same table

I am trying to query a DB with this type of structure
table1
ID -> int
name -> varchar
table2
ID -> int
name1 -> int
name2 -> int
name3 -> int
Where name1 to 3 are table1 IDs. Each line of table2 can have 1 to 3 lines of table1 associated to it and, importantly, the IDs CAN be duplicated (e.g.: name1 and name3 could be the same). The fields are guaranteed to be filled in order (i.e.: if name2 is NULL name3 will also be).
I'm querying the DB like this, in order to get the strings associated to the IDs in the 3 columns:
SELECT t2.ID, t1a.name n1, t1b.name n2, t1c.name n3
FROM table2 t2
LEFT JOIN table1 t1a on t2.name1 = t1a.ID,
LEFT JOIN table1 t1b on t2.name2 = t1b.ID,
LEFT JOIN table1 t1c on t2.name3 = t1c.ID
I'm wondering if there is a way of doing this doing only one LEFT JOIN, or if you could suggest a better table design strategy to achieve this.
Thanks
Select T1.ID
, Min( Case When Z.ColNum = 1 Then Z.Name End ) As n1
, Min( Case When Z.ColNum = 2 Then Z.Name End ) As n2
, Min( Case When Z.ColNum = 3 Then Z.Name End ) As n3
From Table1 As T1
Left Join (
Select ID, 1 As ColNum, name1 As Name
From Table2
Where name1 Is Not Null
Union All
Select Id, 2, name2
From Table2
Where name2 Is Not Null
Union All
Select Id, 3, name3
From Table2
Where name3 Is Not Null
) As Z
On Z.ID = T1.ID
Group By T1.ID