simple mysql query count fails - 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 (...)

Related

Select from 1 table sum from 2 but 1 table has a AND condition

Thanks for assisting with the previous query (SQL Query that selects a column in table 1 and uses that to select sum in table 2) of SUM from 2 tables, I now have a additional Condition for 1 of the tables. I would like to add WHERE Group1 = 1 AND IN/OUT = 'OUT'
I have 3 tables,
Names ,Groups
Names ,Payments
Names ,Payments and IN/OUT
I want to only SUM the OUT Payments in Table 3, I am getting total payments only So FAR is have:
SELECT t1.name1, SUM(t2.sale2),SUM(t3.sale3)
FROM table1 t1 JOIN table2 t2 ON t1.name1 = t2.name2
JOIN table3 t3 ON t1.name1 = t3.name3
WHERE group1 = 1
GROUP BY t1.name1
i would also like to add a zero if there is no data to sum instead of removing the whole record, Currently if a name has no payments in Table 3 but has payments in table 2 it deletes the record.
Please check the query below =>
To Get OutPayment group by Name
SELECT t1.Names,SUM(t3.Payments) As OutPayment
FROM TABLE3 as t3
INNER JOIN TABLE1 as t1 ON t1.Names = t3.Names
INNER JOIN TABLE2 as t2 ON t1.Names = t2.Names
WHERE t1.GroupID = 1 AND t3.INOROUT=2 --INOROUT =2 is OUT and 1 is IN
GROUP BY t1.Names;
To Get TotalOutPayment
SELECT SUM(t3.Payments) As TotalOutPayment
FROM TABLE3 as t3
INNER JOIN TABLE1 as t1 ON t1.Names = t3.Names
INNER JOIN TABLE2 as t2 ON t1.Names = t2.Names
WHERE t1.GroupID = 1 AND t3.INOROUT=2; --INOROUT =2 is OUT and 1 is IN
Note: Code is in DBFiddle too Check the Demo Query Link

mysql sum on JOINED table with different group condition

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

Dynamic inner join using case statement (or similar)

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)

SQL Select where NOT matching specific selection

I have been using the following SQL:
SELECT DISTINCT NAME
FROM Events t1
LEFT JOIN UserHistory t2 ON t1.Name = t2.Event
WHERE t2.Event IS NULL
To select all rows from table 1 where table 2 is Null. This effectively filters out all my Table 1 data where Table 2 has data. However, I want to apply this only when a column in table 2 equals a certain value. Therefore I am looking to do a SELECT * FROM t2 WHERE t2.ID = 1 but am unsure how this fits into this query.
SELECT DISTINCT NAME
FROM Events t1
LEFT JOIN UserHistory t2 ON t1.Name = t2.Event and t2.certain_column = 1234
WHERE t2.Event IS NULL
Also you can try query with NOT EXISTS:
SELECT DISTINCT NAME
FROM Events t1
WHERE NOT EXISTS(SELECT * FROM UserHistory t2
WHERE t1.Name = t2.Event AND t2.ID = 1)
You need to add the predicate to the JOIN condition:
SELECT DISTINCT NAME
FROM Events t1
LEFT JOIN UserHistory t2 ON t1.Name = t2.Event AND t2.ID = 1
WHERE t2.Event IS NULL;
If you add it to the WHERE you effectively turn your outer join into an inner join, meaning no rows will be returned (since NULL = 1 evaluates to false)

sql query question

I have tables
table 1
id text
1 A
1 B
2 C
table 2
id text
1 x
1 f
2 y
2 z
I want to join them this way
1 A x
1 B f
2 C y
2 z
In other words i want to see all texts from table1 and table2 grouped by id, with no repeats.
Any ideas?
Update: as they say in comments, the logic is not clear, I'll try to explain.
I have current values in table_1 and deleted values in table_2.
Customer wants to see current values and deleted values in one table grouped by some id.
Simple solution to get something close to what you're looking for
SELECT t1.id, t1.text, t2.text
FROM tbl_1 t1
INNER JOIN tbl_2 t2
ON t1.id = t2.id
this will create output
1 A x
1 B x
2 C y
2 C z
Only different is now that the duplicated texts x and C should somehow removed.
Update
precondition: duplicates per id are either in tbl_1 or tbl_2 not both !
Joining a grouped select in addition to above simple solution will allow to create kind of "CASE-Filters" to get your desired output.
SELECT
t1.id,
CASE
WHEN t2.text = txt_i2 THEN t1.text
END AS txt_t1,
CASE
WHEN t1.text = txt_i1 THEN t2.text
END AS txt_t2
FROM (
SELECT
i1.id,
i1.text AS txt_i1,
i2.text AS txt_i2
FROM tbl_1 i1
INNER JOIN tbl_2 i2
ON i1.id = i2.id
GROUP BY id
) i
INNER JOIN tbl_1 t1
ON i.id = t1.id
INNER JOIN tbl_2 t2
ON t1.id = t2.id
You should create a view of the tbl_1-tbl_2-join to get more readable SQL:
CREATE OR REPLACE VIEW V_tbl_1_2 AS (
SELECT
t1.id,
t1.text AS txt_1,
t2.text AS txt_2
FROM tbl_1 t1
INNER JOIN tbl_2 t2
ON t1.id = t2.id
)
;
SELECT
t.id,
CASE
WHEN t.txt_2 = i.txt_2 THEN t.txt_1
END AS txt_t1,
CASE
WHEN t.txt_1 = i.txt_1 THEN t.txt_2
END AS txt_t2
FROM V_tbl_1_2 t
INNER JOIN (
SELECT *
FROM V_tbl_1_2
GROUP BY id
) i ON t.id = i.id
;
USE MYSQL VIEW OR JOIN
This works if you can have no more than two items per id in either table and if neither one has complete duplicates. (And I must also add that this can only work if MySQL is able to swallow this monster and not choke with it.)
SELECT
COALESCE (t1.id, t2.id) AS id,
t1.text AS text1,
t2.text AS text2
FROM (
SELECT
t.id,
t.text,
CASE t.text WHEN m.text THEN 1 ELSE 2 END AS rowid
FROM table_1 t
INNER JOIN (
SELECT id, MIN(text) AS text
FROM table_1
GROUP BY id
) m ON t.id = m.id
) t1
FULL JOIN (
SELECT
t.id,
t.text,
CASE t.text WHEN m.text THEN 1 ELSE 2 END AS rowid
FROM table_2 t
INNER JOIN (
SELECT id, MIN(text) AS text
FROM table_2
GROUP BY id
) m ON t.id = m.id
) t2
ON t1.id = t2.id AND t1.rowid = t2.rowid
ORDER BY COALESCE (t1.id, t2.id), COALESCE (t1.rowid, t2.rowid)