I have 3 tables: table1, table2 & table3
I make a select query from table1 which LEFT JOINS the other two tables. In the select I have a group_concat which takes a value from table3. Everything works well until a row with a specific row doesn't exist. The group_concat list becomes empty. Instead, I would like it to set values in the group_concat to NULL for the ones where the rows doesn't exist.
Like I said if the value in table3 exist for all the rows in table2 then it works. If not, the whole group_concat is empty.
Some "simplified" code of what I got so far:
SELECT
table1.table2Id,
table1.dateAdded,
IF(COUNT(table2.table3Id) = COUNT(*), GROUP_CONCAT(table2.table3Id), NULL) as group1,
IF(COUNT(table3.ext) = COUNT(*), GROUP_CONCAT(table3.ext), NULL) as group2
FROM table1
LEFT JOIN table2 ON
table2.id = table1.table2Id
LEFT JOIN table3 ON
table3.id = table2.table3Id
Fixed it by changing
IF(COUNT(table3.ext) = COUNT(*), GROUP_CONCAT(table3.ext), NULL) as group2
to
GROUP_CONCAT(IFNULL(table3.ext, NULL)) as group2
In your situation when you are using joins use derieved sub query in join and use IFNULL and set its default value to 0 then in the outer table this value (0) will be used if there comes null.
EDITS :
as there is no data to test you can do it like this. Use INNER JOIN instead of left join.
SELECT
table1.table2Id,
table1.dateAdded,
IF(COUNT(table2.table3Id) = COUNT(*), GROUP_CONCAT(table2.table3Id), NULL) as group1,
IF(COUNT(table3.ext) = COUNT(*), GROUP_CONCAT(table3.ext), NULL) as group2
FROM table1
INNER JOIN table2 ON
table2.id = table1.table2Id
INNER JOIN table3 ON
table3.id = table2.table3Id
Also try using derieved sub query
SELECT
table1.table2Id,
table1.dateAdded,
IF(COUNT(t2.table3Id) = COUNT(*), GROUP_CONCAT(t2.table3Id), NULL) as group1,
IF(COUNT(table3.ext) = COUNT(*), GROUP_CONCAT(table3.ext), NULL) as group2
FROM table1
LEFT JOIN (
SELECT
id,
IFNULL(table3Id,0) as table3Id,
table3Id
FROM table2
GROUP BY id table3Id
)as t2 ON t2.id = table1.table2Id
INNER JOIN table3 ON table3.id = t2.table3Id
Related
I am trying to get two counts of the occurence of an event with two different WHERE clauses. I would like the end result columns to be displayed side by side. Lastly, for each count, I need to obtain a display name column from another table. I would like to do all this in a query.
EDIT
Changed the grouping variable to table1.column1 (it's equivalent since it is the name rather than the id, but both should be unique.
SELECT table1.column1, COUNT(DISTINCT table2.column1) AS newcolumn1
FROM table2
LEFT JOIN table1 ON (table1.column2 = table2.column2)
WHERE table2.column3 != 'var1'
GROUP BY table1.column1
UNION ALL
SELECT table1.column1, COUNT(DISTINCT table2.column1) AS newcolumn2
FROM table2
LEFT JOIN table1 ON (table1.column2 = table2.column2)
WHERE table2.column3 = 'var2'
GROUP BY table1.column1
This sort of does what I want, but it stacks the columns instead of displaying them side by side. The end game is to have a column that is the ratio of newcolumn 1 and newcolumn 2. Unfortunately, this is a far as I managed to get.
You could try using separated left join instead of union
select table1.column1, tvar1.newcolumn1, tvar2.newcolumn2
from table1
left join (
SELECT table1.column1, COUNT(DISTINCT table2.column1) AS newcolumn1
FROM table2
LEFT JOIN table1 ON (table1.column2 = table2.column2)
WHERE table2.column3 = 'var1'
GROUP BY table1.column1
) tvar1 on tvar1.column1 = table1.column1
left join (
SELECT table1.column1, COUNT(DISTINCT table2.column1) AS newcolumn2
FROM table2
LEFT JOIN table1 ON (table1.column2 = table2.column2)
WHERE table2.column3 = 'var2'
GROUP BY table1.column1
) tvar2 on tvar2.column1 = table1.column1
I have two tables bound through an ID field:
table1: id, name, type
table2: id, id_table1, date, status
I have to collect all the records of the table1 that have a certain value of type field and that are not been referenced in table2 plus all the records of table1 referenced in table2 that have a certain status field value.
For the first part if I remember correctly I can use the LEFT JOIN command:
LEFT JOIN table1.name
LEFT JOIN table2
ON table2.id_table1 = table1.id
WHERE (table1.value = 'value1') AND (table2.id_table1 IS NULL);
but for the second part I'm getting lost...
I'm using MySQL 5.6 and I would like to define a View to handle this.
SELECT t1.*, t2.*
FROM table1 t1
LEFT JOIN table2 t2
ON table2.id_table1 = table1.id
WHERE (t1.type= 'value1' AND t2.id IS NULL)
OR (t2.status = 'certain status' )
I would think you could just change the WHERE to:
WHERE (table1.value = 'value1')
AND (table2.id_table1 IS NULL
OR
([the other table2 status criteria)
)
;
You can try this...
SELECT T1.*,T2.*
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.Id=T2.Id_Table1
WHERE T1.Value = 'value1' AND T2.id_table1 IS NULL
UNION
SELECT T1.*,T2.*
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.Id=T2.Id_Table1
WHERE T2.Status= 'Status Criteria'
Is is possible to simplify this UNION to avoid the near redundancy of the queries being unioned? As seen here, both queries are similar. They just join on a different column in table2. The reason i use Union, instead of just Inner Joining 2x in the same query is because the results must be in 1 column by virtue of the fact that this queries is used as a subquery.
SELECT t1.id as id
FROM table1 g
INNER JOIN table2 t1 on g.t_id = t1.id
WHERE g.id=1
UNION
SELECT t2.id as id2
FROM table1 g
INNER JOIN table2 t2 on g.t2_id = t2.id
WHERE g.id=1
I don't see why this couldn't be treated as a simple inner join that can be satisfied by a match in either of two predicates. I've removed the original table aliases of t1, t2, and g for the sake of clarity. Since I don't know if the query could produce duplicate rows, I used DISTINCT in order to collapse duplicate rows in the same manner that the UNION did in the original query.
SELECT DISTINCT table2.id
FROM table1
INNER JOIN table2
ON ( table1.t_id = table2.id OR table1.t2_id = table2.id )
WHERE table1.id = 1
;
It is possible to do with two joins, and the IFNULL() function:
SELECT IFNULL (t1.id, t2.id) as id
FROM table1 g
INNER JOIN table2 t1 on g.t_id = t1.id
INNER JOIN table2 t2 on g.t2_id = t2.id
WHERE g.id=1
You might find this simpler:
select distinct t.id
from table2 t
where t.id in (select g.t_id from table1 g) or
t.id in (select g.t2_id from table1 g)
However, the performance would be awful on MySQL. You can also do:
select distinct t.id
from table2 t
where exists (select 1 from table1 g where g.t_id = t.id or g.t2_id = t.id)
The second version should work better in MySQL.
SELECT
count(t1.id) AS c1
FROM
table2
LEFT JOIN table1 AS t1 ON (t1.uid = table2.uid)
WHERE
table2.mode = 'ls'
GROUP BY
t1.id
c1 = 6 -> CORRECT!
SELECT
count(t2.id) AS c2
FROM
table2
LEFT JOIN table1 AS t2 ON (t2.pid = table2.id)
WHERE
table2.mode = 'ls'
GROUP BY
t1.id
c2 = 1 -> CORRECT!
SELECT
count(t1.id) AS c1,
count(t2.id) AS c2
FROM
table2
LEFT JOIN table1 AS t1 ON (t1.uid = table2.uid)
LEFT JOIN table1 AS t2 ON (t2.pid = table2.id)
WHERE
table2.mode = 'ls'
GROUP BY
t1.id
c1 = 6 -> CORRECT!
c2 = 6 -> WRONG!
How do I request both counts in one query, without getting wrong results?
I need to count two different requests at the same table (table1).
so, I'm using an alias for both request. (t1). Each alias-request is working fine alone. If I use both in the same query, i got wrong results.
count() will get you the number of records that are returned by your query. Since if you removed the counts and replaced it with * you would have 6 rows both of those counts are giving you 6.
Is there any reason why you cant use two sub selects and return the result of each of those?
So:
SELECT subQ1.c1, subQ2.c2 FROM
(SELECT count(t1.id) AS c1 FROM table2
LEFT JOIN table1 AS t1 ON (t1.uid = table2.uid)
WHERE table2.mode = 'ls') as subQ1,
(SELECT count(t2.id) AS c2 FROM table2
LEFT JOIN table1 AS t2 ON (t2.pid = table2.id)
WHERE table2.mode = 'ls') as SubQ2;
I believe your problem on the full query is your group by function. You are grouping by t.id, thus a1.id will have a different count based on how many rows you have.
What I mean by this is if there are 6 rows in table t, then count is going to return 6 for table t; but also since there looks to be a 1 to 1 relation on table a, there are 6 matching rows in table a to the 6 matching rows in table t. such that
t.id = a.id
1 = 1
2= 2 ...etc.
Thus your count is returning rows versus the count you believe you should have? I believe sum function is what you want to use here.
You could try this...but I'm not really sure what you're trying to do.
SELECT (...)
count(CASE WHEN t1.uid = t3.uid THEN t1.id ELSE NULL END) AS CBanz,
count(CASE WHEN ta1.pid = t3.id THEN a1.id ELSE NULL END) AS CBanz1
FROM
t0
LEFT JOIN (...)
LEFT JOIN t1 ON (t1.uid = t3.uid)
LEFT JOIN t1 AS a1 ON (a1.pid = t3.id)
WHERE (...)
I have a complicated MYSQL query question here. I try my best to explain my problem.
I have 4 tables. mid is a foreign key between the tables. table4 is NOT a compulsory table source. However I like it returns all the rows even there are no match data from table4. So that I write a query script as following.
I'm not sure is it the logic way to write such query script but what I know that the syntax is wrong.
SELECT *
FROM table1, table2, table3,
(SELECT xx
FROM table4
RIGHT JOIN table1 ON table1.mid = table4.mid)
WHERE table1.mid = table2.mid
AND table1.mid = table3.mid
AND tt = 'a'
AND type = 1
GROUP BY table1.mid
ORDER BY xx DESC, table1.name ASC;
You have to do a left join between table1 & table4:
SELECT *
FROM table1
JOIN table2 ON table1.mid = table2.mid
JOIN table3 ON table1.mid = table3.mid
LEFT JOIN table4 ON table1.mid = table4.mid
WHERE tt = 'a'
AND type = 1
GROUP BY table1.mid
ORDER BY xx DESC, table1.name ASC;