Complex query over two tables - mysql

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?

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

SQL Combining data from 3 tables to from a 4th table based on some conditions

I have 3 tables:-
table1 :-
ReportType | ResourceId
t2 123
t3 5
table2:-
Id | Name | Created
1 A 10
2 B 11
123 C 12
table3:-
Id | Name | Created
4 D 13
5 E 14
6 F 15
table1's ResourceId and table2 and 3's Id column have same values
I want to create a 4th table like this:-
ReportType | ResourceId | Name | Created
t2 123 C 12
t3 5 E 14
such that wherever table1's ReportType is t2 I want the Name and Created value from table2 for the condition table1.ResourceId = table2.Id and wherever table1's ResourceType is t3 I want the Name and Created value from table3 for the condition table1.ResourceId = table3.Id.
PS: This isn't some sort of HomeWork. I have been stuck at this query for the past 1 hour, I have read various answers and tried a few queries of my own before posting the question. Any help would really be appreciated.
Explanation in comments :)
--here we join first and second table, but we filter results to include only ReportType = t2
select t1.ReportType, t1.ResourceId, t2.Name, t2.Created from table1 as t1 join table2 as t2 on t1.ResourceId = t2.id
where t1.ReportType = 't2'
union all
--here we join first and third table, but we filter results to include only ReportType = t3
select t1.ReportType, t1.ResourceId, t3.Name, t3.Created from table1 as t1 join table3 as t3 on t1.ResourceId = t3.id
where t1.ReportType = 't3'
You can use the below query:
select report_type, resourceid,name, created from dbo.t2, dbo.t1
where report_type='t2' and ResourceId=id
UNION
select report_type, resourceid,name, created from dbo.t3, dbo.t1
where report_type='t3' and ResourceId=id;

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.

MySQL moving average calculation

How can i edit the ON operator part of my query below such that i would like the current code to work where id<=14 (which is t2.id <= t1.id as shown below) so when t1 id =14, t2 is the cumulative id from 1 to 14 (as it is now).
but for id >14 I would like the ON operator to be (t2.id=t1.id>=t1.id-2 and <=t1.id) so when t1 id=15, t2.id should be between 13 and 15. when t1 id =16, t2.id should be between 14 and 16 and so on.
I'm doing this because when i calculate col E for ids after id=14, i am only interested in getting the average of the previous 2 rows for C and D on a moving average.
My query has 2 sub queries and it updates column E. The table looks like this:
--------------------------
id | A | B | E |
--------------------------
1 | NULL | NULL |NULL|
--------------------------
2 | 4 | 6 |NULL|
--------------------------
3 | 6 | 9 |NULL|
--------------------------
This is my query where i got help from this link: Mysql Nested sub queries unknown column error
Update t join
(SELECT t1.id ,ifnull(t1.A/AVG(t2.A),0) C ,ifnull(t1.B/AVG(t2.B),0) D
FROM t t1
JOIN t t2
ON t2.id <= t1.id
group by t1.id ) AS tt
on(t.id = tt.id)
SET E = (tt.C + tt.D)/2;
Thanks,
where id<=14 (which is t2.id <= t1.id as shown below) so when t1 id =14, t2 is the cumulative id from 1 to 14 (as it is now).
Update t join
(
SELECT t1.id ,ifnull(t1.A/AVG(t2.A),0) C ,ifnull(t1.B/AVG(t2.B),0) D
FROM t t1
JOIN t t2
ON case when t2.id < 15 then t2.id <= t1.id else t2.id=t1.id>=t1.id-2 and <=t1.id end
group by t1.id
) tt on(t.id = tt.id)
SET E = (tt.C + tt.D)/2;

SELF JOIN Unique Resultset Issue - MySQL

I have a table as below
ID | CID
1 | 3
2 | 0
3 | 4
4 | 0
5 | 0
6 | 3
Below is the SQL query I use which is SELF JOIN.
SELECT t1.ID
FROM `tbl_a` AS t1 JOIN `tbl_a` AS t2
ON t1.ID = t2.CID
Which gives me O/P as below.
ID | CID
3 | 4
4 | 0
But what I want as an O/P is 1,3,4,6.
Logic of the O/P is Rows IDs or CIDs which are being used. If I explain more When the ID is 1 CID 3, When the ID is 3 CID is 4, When the ID is 6 CID is 3. When I get the unique IDs & CIDs that are used in the table would be 1,3,4,6.
Final Correct O/P Required is below.
ID
1
3
4
6
How can I get it done?
Not sure what you're trying to do. I think you are saying you want the ID of rows that have a non-zero CID or that are referenced by the CID column. (?) Try this:
SELECT ID FROM tbl_a AS t1 WHERE CID <> 0 OR EXISTS(SELECT * FROM tbl_a AS t2 WHERE t2.CID = t1.ID) ORDER BY ID
Try this
SELECT t2.ID
FROM `tbl_a` AS t1 JOIN `tbl_a` AS t2
ON t1.ID = t2.CID
OR t2.ID = t1.CID
GROUP BY t2.ID
I think this may be what you want:
select ID
from tbl_a
where id in (3, 4) or cid in (3, 4);