I have two tables in MySQL DB; table1, table2.
Both of them have a single column (float) values. It's actually a dump from our research project which produces a single value result.
And many of these values get repeated and sorting and filtering them in Python would be cumbersome, so I though perhaps dumping them in a table in DB would be quicker.
So the end result from the SQL query is the following grouped by the value:
value table1_count table2_count
1.0 0 1
1.1 1 3
2.1 4 5
The query I am coming up with is the following:
select everything.value, everything.count1, everything.count2
from
((
select X as value, count(*) from table1
) union all (
select X as value, count (*) from table2
)) everything
group by everything.value
into outfile "/count";
Any suggestions?
Thanks,
You can't do counts by group in the inner queries, since you're defining the groups in the outer query. This should be simpler:
select everything.value, count(*)
from
(
select X as value from table1
union all
select X from table2
) everything
group by value
into outfile "/count";
Also here's some trivia: when you use UNION, you need to define column aliases only in the first query unioned.
Re your comment. Here's one solution:
select everything.value, sum(t = 'success') as s, sum(t = 'failure') as f
from
(
select X as value, 'success' as t from table1
union all
select X, 'failure' from table2
) everything
group by value
into outfile "/count";
This uses a trick in MySQL that boolean expressions return 0 for false or 1 for true. So when you sum up a bunch of expressions, you get a count of the rows where the expression is true. (Don't rely on this trick in other brands of SQL database.)
Related
Here is two equals query at first sight:
SELECT obj_id
FROM obj t JOIN joined_a a ON t.`id` = a.`obj_id`
UNION
SELECT obj_id
FROM obj t JOIN joined_b b ON t.`id` = b.`obj_id`;
and
SELECT obj_id
FROM obj t JOIN joined_b b ON t.`id` = b.`obj_id`
UNION
SELECT obj_id
FROM obj t JOIN joined_a a ON t.`id` = a.`obj_id`;
They are different only with select's sequence.
result rows quantity from these two queries are different!
How does it possible?
If I add DISTINCT to each SELECT ... rows quantity will have NEW value, the biggest value!
If I add brackets to each SELECT like
(select ...)
UNION
(select ...)
rows quantity will have the DISTINCT's value.
These two queries will return the same rows, but not necessarily in the same order.
UNION dedupes the results for you, so the DISTINCTs do nothing and the size of the result set is the same regardless of the SELECT order.
The only explanation that fits your test is that some more data was inserted in between the running of the two.
You are right!
I got into an insidious trap with SQLYog ultimate GUI interface v11.11 BUG-feacher!!!
GUI adds to each query LIMIT 0, 1000; suffix
:(
check queries at command line and it's work fine.
I have the following query
SELECT *
FROM(
(SELECT
MAX(c.start_time) as start_1
FROM
c1 c)
UNION ALL
(SELECT
MAX(cc.created_at) as ccmax
FROM
cc1)
) as t
I'd like to have the result in a table with 2 columns start_1 and cmax instead of the single column I get with all the different results listed.
How should I do it? I ended up in a subselect believing this would have done the job.
For the data to be in two columns you would have to use a sub select.
SELECT
MAX(c1.start_time) as start_1, (SELECT MAX(cc1.created_at) FROM cc1) as ccmax
FROM c1
In the 2 queries below the result set would be the same, but I was wondering if there would be any difference in speed because of the order of the comparison arguments in the ON clauses.
In the first query it matches table1.c1 = table2.c1, and the second the other way around.
SELECT * FROM table1 JOIN table2 ON (table1.c1 = table2.c1)
Or
SELECT * FROM table1 JOIN table2 ON (table2.c1 = table1.c1)
The two queries are strictly the same, there is no difference between them.
It just a convention to use the first form:
SELECT * FROM table1 JOIN table2 ON (table1.c1 = table2.c1)
Ever since the boolean expression inside ON clause returns TRUE, a record will be send to the result set output. If one of the tables returns 0 record, even if the ON clause returns TRUE, result set will be empty. So there is no difference that how you'd like to write a boolean expression inside the ON clause. Like this which means Cross Join!
Cheers
Select *
From dbo.Person As A
Inner Join
dbo.PersonOrder As B
On 1 = 1
Is there a way to write a single query to check if a set of rows matches a set of values? I have one row per set of values that I need to match and I'd like to know if all rows are matched or not. I could perform this via multiple queries such as:
select * from tableName where (value1, value2) = ('someValue1', 'someValue2')
select * from tableName where (value1, value2) = ('someOtherValue1', 'someOtherValue2')
...and so on, up to an arbitrary number of queries. How could this sort of thing be re-written as a single query where the query returns ONLY if all values are matched?
You could try something like:
select t.*
from tableName t
join (select 'someValue1' value1, 'someValue2' value2 union all
select 'someOtherValue1', 'someOtherValue2') v
on t.value1 = v.value1 and t.value2 = v.value2
where 2=
(select count(distinct concat(v1.value1, v1.value2))
from (select 'someValue1' value1, 'someValue2' value2 union all
select 'someOtherValue1', 'someOtherValue2') v1
join tableName t1
on t1.value1 = v1.value1 and t1.value2 = v1.value2)
If you have a large number of value pairs that you want to check, it may be easier to insert them into a temporary table and use the temporary table in the above query, instead of two separate hard-coded virtual tables.
What about:
SELECT *
FROM tableName
WHERE value1 IN ('someValue1', 'someOtherValue1') AND
value2 IN ('someValue2', 'someOtherValue2')
Match if exactly two records found
Select students who got q13 wrong and Q14 right
SELECT qa.StudentID FROM questionAnswer qa, Student s
WHERE qa.StudentID=s.StudentID AND
((QuestionID=13 AND Pass=0) OR (QuestionID=14 AND Pass=1))
GROUP BY qa.StudentID
HAVING COUNT(*)=2;
The Where clause matches any records where q14 is correct and q13 is incorrect
We then group by the StudentID
The having requires there to be two records
if select * from table where x=1 returns 0 rows, then I need select * from table where x=2 [or some other query]. Is it possible to do this in a single MySQL query with a conditional statement?
Edit: All answers with UNION work, but only if both queries select from the same table (or tables with the same number of columns). What if the second query is applied on a different table with joins?
Let me write down the my queries to make the question more clear:
1st:
SELECT table1.a, table2.b from table1 LEFT JOIN table2 ON table2.x= table1.x
WHERE .....
if the result from the 1st one is null then:
2nd:
SELECT table1.a FROM table1
WHERE ....
I will be using the rows from the 1st query if it returns any, otherwise the 2nd one will be used.
This appears to work from a quick test I just did and avoids the need to check for the existence of x=1 twice.
SELECT SQL_CALC_FOUND_ROWS *
FROM mytable
WHERE x = 1
UNION ALL
SELECT *
FROM mytable
WHERE
FOUND_ROWS() = 0 AND x = 2;
Edit: Following your clarification to the question obviously the 2 queries will need to be UNION compatible for the above to work.
The answer to your updated question is No. This is not possible in a single query. You would need to use some conditional procedural logic to execute the desired query.
You could try...
SELECT *
FROM mytable
WHERE x = 1
UNION
SELECT *
FROM mytable
WHERE x = 2 AND
NOT EXISTS (SELECT *
FROM mytable
WHERE x = 1);
if you don't consider it too ghastly a hack.
yes
Subqueries with EXISTS or NOT EXISTS
http://dev.mysql.com/doc/refman/5.1/en/exists-and-not-exists-subqueries.html
example :
SELECT column1 FROM t1 WHERE NOT EXISTS (SELECT * FROM t2);
If the two queries return different number of columns, you can pad one of the results with empty columns and also add an identifier column first.
SELECT SQL_CALC_FOUND_ROWS 1 query_type, mytable.*,
'' col1, '' col2, '' col3, '' col4
FROM mytable
WHERE x = 1
UNION ALL
SELECT 2, mytable2.*
FROM mytable2
WHERE
FOUND_ROWS() = 0 AND x = 2;
Where mytable2 has 4 more columns than mytable.
The simplest explanation is that:
SELECT IF(1 = 2,'true','false'); --> false
SELECT IF(1 = 1,' true','false'); --> true
SELECT IF(1 = 2,' true','false'), IF(1 = 1,' true','false'); --> false | true
The 'if' statement give some functionality to selected values.
The structure is something like this:
SELECT IF(<your statement>), ...<selected params>... FROM <your tables>
A great explanation can be found here.
SQL_CALC_FOUND_ROWS and FOUND_ROWS cannot be used in a single query, even if separate by UNION statements.
The correct way to do this would be:
WITH my_cte AS
(
SELECT * from original_set
)
SELECT * FROM my_cte
UNION ALL
SELECT opt.* FROM optional_set opt JOIN (SELECT count(*) v FROM my_cte) count ON count.v=0;
With the JOIN and the UNION ALL the performance of this query is almost equivalent to either of the individual standalone queries
you can use EXIST and NOT EXIST statement to check that result is null or not. if result is Null then you can get value from table2.