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
Related
I need to join two tables in SQL. There are no common fields. But the one table have a field with the value krin1001 and I need it to be joined with the row in the other table where the value is 1001.
The idea behind the joining is i have multiple customers, but in the one table there customer id is 'krin1001' 'krin1002' and so on, in this table is how much they have sold. In the other table there customer is is '1001' '1002' and so on, and in this table is there name and adress and so on. So it will always be the first 4 charakters i need to strip from the field before matching and joining. It might not always be 'krin' i need it to work with 'khjo1001' also, and it still needs to join on the '1001' value from the other table.
Is that possible?
Hope you can help me.
You need to use substring:
ON SUBSTRING(TableA.Field, 5, 4) = TableB.Field
Or Right:
ON RIGHT(TableA.Field, 4) = TableB.Field
You can also try to use CHARINDEX function for join operation. If value from table1 contains value from table2 row will be included in result set.
;WITH table1 AS(
SELECT 'krin1001' AS val
UNION ALL
SELECT 'xxx'
UNION ALL
SELECT 'xyz123'
),
table2 AS(
SELECT '1001' AS val
UNION ALL
SELECT '12345'
UNION ALL
SELECT '123'
)
SELECT * FROM table1 AS t
JOIN table2 AS T2 ON CHARINDEX(T2.val, T.val) > 0
Use it as:
SELECT
*
FROM table t1
INNER JOIN table t2 ON RIGHT(t1.col1, 4) = t2.col1;
I have a complex select query from table1 that returns 2 columns of data (id and value)
I want to update columns id and value of table2 with that data.
How can i do it ?
I have tried something like this
update table2 set (id, value) values (select ....)
and other things, but no results :P
NOTE & EDIT: I've seen about UPDATE INNER JOIN but the problem is that my select is complex ... it's like
select distinct(colA), sum(case statement....) as c1, sum(case statement...) as c2 from table2 group by colA
and colA, c1 and c2 is what i want to update in other table
thank you
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.
I use a MySQL DB, and I would like to update a field in a table based on another. Something like:
UPDATE table1
SET field1 = table2.id
WHERE field2 IN (
SELECT table2.name
FROM table2
);
I know that this query wouldn't work, but here is the idea. Is that even possible to do?
You can use a correlated sub query as below. This assumes there will be exactly one matching value returned. It will raise an error if more than one matching value is returned or set the field to null if zero are returned. If that last behaviour isn't desirable you will need a where clause.
UPDATE table1
SET field1 = (SELECT DISTINCT table2.ValueColumn
FROM table2
WHERE table2.JoinColumn = table1.JoinColumn)
Edit
To review records with 0 or more than 1 matches you could use
SELECT table1.JoinColumn, COUNT(DISTINCT table2.ValueColumn)
FROM table1
LEFT JOIN table2
ON table2.JoinColumn = table1.JoinColumn
GROUP BY table1.JoinColumn
HAVING COUNT(DISTINCT table2.ValueColumn) <> 1
I'd like to do an insert select where the select statement has aggregate columns for use by a "HAVING" clause, but where I do not actually want those columns to be inserted. A simple example:
INSERT INTO table1 ( a )
SELECT a, MAX (b) AS maxb FROM table2
GROUP BY a
HAVING maxb = 1
Of course, this won't work because there are a different number of columns in the INSERT and the SELECT. Is there as simple way to make this work? I was hoping I could define some sort of null column in the INSERT field list, or something. I was hoping to avoid a subquery in my SELECT statement, although I could probably do it that way if necessary.
INSERT INTO table1 ( a )
SELECT a FROM (SELECT a, MAX (b) AS maxb FROM table2
GROUP BY a
HAVING maxb = 1) t
You can rewrite the query like this
INSERT INTO table1 ( a )
SELECT a FROM table2
GROUP BY a
HAVING MAX (b) = 1