So I have two tables with:
t1 = (submission_id,field_id,value),
t2 = (submission_id, other_fields....).
Now t1 contains a bunch of things in value, i.e. field_id = 8 gives value = firstname, field_id = 9 gives value = lastname etc. What I want is a table with (submission_id,firstname,lastname,...).
What I have some up with so far is something like this:
SELECT (SELECT value FROM t1 INNER JOIN t2 ON (t2.submission_id = t1.submission_id)
where field_id = 8),
(SELECT value FROM t1 INNER JOIN t2 ON (t2.submission_id = t1.submission_id) where field_id = 9)
But this just gives me an error about the fact that there is more than one result to each sub-query. I could use union, but this obviously just gives me horribly stacked results.
Anyone have any better idea?
If you don't need the join to t2 then do a self join:
SELECT t1a.submission_id, t1a.value firstname, t1b.value lastname
FROM t1 t1a INNER JOIN t1 t1b
ON t1b.submission_id = t1a.submission_id AND t1a.field_id = 8 AND t1b.field_id = 9
I kept the join on submission_id if this is the link between the 2 values.
One solution that is quite scalable is to use conditional aggregation:
select
submission_id,
max(case when field_id = 8 then value end) firstname,
max(case when field_id = 9 then value end) lasstname
from t1
group by submission_id
The advantage of this technique is that you can easily add more columns by extending the query with more max(case ...) expressions, so it scales better than the self-join solution.
If for some reason you also need to bring t2, then you can join and add columns from t2 in the from and group by clauses:
select
t1.submission_id,
t2.other_field1,
t2.other_field2,
max(case when t1.field_id = 8 then t1.value end) firstname,
max(case when t1.field_id = 9 then t1.value end) lasstname
from t1
inner join t2 on t2.submission_id = t1.submission_id
group by t1.submission_id, t2.other_field1, t2.other_field2
Related
I have the following query:
SELECT c.text1, sum(c.num1), sum(c.num2), sum(c.num3),
(SELECT count(id) FROM table2 WHERE type = 1 AND txt = c.text1 AND spec_id = c.sp_id)
FROM table1 as c
WHERE c.type = 1
GROUP BY c.text1, c.sp_id
Is there a workaround to loose the c.sp_id from the GroupBy clause somehow? I know that if I remove it MySQL will return an error.
Or is there a way to group the results of this query by c.text1 only?
If I understand the problem correctly, you need to do two separate aggregations. This is one version of the query:
SELECT c.text1, c.sum1, c.sum2, c.sum3, t2.cnt
FROM (SELECT c.text1, sum(c.num1) as sum1, sum(c.num2) as cum2, sum(c.num3) as sum3
FROM table1 c
GROUP BY c.text1
) c LEFT JOIN
(SELECT txt, count(*) as cnt
FROM table2 t2
WHERE t2.type = 1 AND
EXISTS (SELECT 1
FROM table1 c2
WHERE t.txt = c2.txt AND c2.type = 1 AND
t.spec_id = c2.sp_id
)
) t2
ON t2.txt = c.text1
WHERE c.type = 1;
I have a query as the following
SELECT
sum(price),
count(id),
sum case(when spec='bath' then price else 0 END) as bath_money
FROM
table1
LEFT JOIN table2 ON table1.id = table2.fkt1
LEFT JOIN table3 ON table2.id = table3.fkt2
WHERE 1
group by sale;
Now my problem is that table 3 has 2 rows for each row in Table 2. Table 2 is the one I actually use to add up sales and to sum price but since I need to left join for Table 3 everything is added twice.
Would there be a way of adding up prices of table 2 ignoring all double lines generated by joining Table 3? Otherwise I'd just write another query, but I'd like to know whether I can do a sum ignoring a specific join??
Does this work :
SELECT
sum(price),
count(id),
sum(case when spec='bath' then price else 0 END) as bath_money
FROM table1 t1
LEFT JOIN table2 ON table1.id = table2.fkt1
LEFT JOIN (select * from table3 GROUP BY fkt2) table3a ON table2.id = table3a.fkt2
group by sale;
You can try something like
SELECT
sum(t1.price),
count(t1.id),
sum (case when t2.spec='bath' then t2.price else 0 END) as bath_money
FROM
table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.fkt1
LEFT JOIN table3 t3 ON t2.id = t3.fkt2
group by t1.sale
I'm trying to inner join table1 <- to -> table2, table3, table4 OR table5 depending on a field present in table1. So, if the field information in table1 has the value example_get_from_two I should inner join table1 with table2 as to obtain a given row, if in another row table1 has the value example_get_from_three I should inner join table1 with table3 and so on. This is the query I tried, but it returned zero rows:
SELECT n.notification_type,
(CASE WHEN n.notification_type = 'two' AND n.information = t2.somefield
THEN t2.anotherfield
WHEN n.notification_type = 'three'
THEN (CASE WHEN t3.field = '1' THEN t3.otherfield ELSE t3.yetanotherfield END)
WHEN n.notification_type = 'four' AND t4.field = n.information
THEN t4.anotherfield
WHEN n.notification_type = 'five'
THEN t5.field
END) AS information FROM table0 zero, notifications n
INNER JOIN table1 t1 ON(n.information=t1.somefield AND n.notification_type = 'something')
INNER JOIN table2 t2 ON(n.information=t2.somefield AND n.notification_type = 'something')
INNER JOIN table3 t3 ON((n.information=t3.somefield OR n.information=t3.someotherfield) AND n.notification_type = 'something')
WHERE zero.field ='something' AND n.id = zero.id
Unfortunately this retrieves zero rows and shouldn't , probably because all joins are made despite the actual value of information, and n.notification_type = "something". Is this possible with cases or similar? What I'd like to obtain is
fromfield1 | fromfield2 | fromfield3 (this one is "dynamic" and
depends on the joined table)
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
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 (...)