Query Two Tables - but not trying to JOIN? - mysql

I have two tables that almost have identical columns. The first table contains the "current" state of a particular record and the second table contains all the previous stats of that records (it's a history table). The second table has a FK to the first table.
I'd like to query both tables so I get the entire records history, including its current state in one result. I don't think a JOIN is what I'm trying to do as that "joins" multiple tables "horizontally" (one or more columns of one table combined with one or more columns of another table to produce a result that includes columns from both tables). Rather, I'm trying to "join"(???) the tables "vertically" (meaning, no columns are getting added to the result, just that the results from both tables are falling under the same columns in the result set).
Not exactly sure if what I'm expressing make sense -- or if it's possible in MySQL.

To accomplish this, you could use a UNION between two SELECT statements. I would also suggest selecting from a derived table in the following manner so that you can sort by columns in your result set. Suppose we wanted to combine results from the following two queries:
SELECT FieldA, FieldB FROM table1;
SELECT FieldX, FieldY FROM table2;
We could join these with a UNION statement as follows:
SELECT Field1, Field2 FROM (
SELECT FieldA AS `Field1`, FieldB AS `Field2` FROM table1
UNION SELECT FieldX AS `Field1`, FieldY AS `Field2` FROM table2)
AS `derived_table`
ORDER BY Field1 ASC, Field2 DESC
In this example, I have selected from table1 and table2 fields which are similar, but not identically named, sharing the same data type. They are matched up using aliases (e.g., FieldA in table1 and FieldX in table2 both map to Field1 in the result set, etc.).
If each table has the same column names, field aliasing is not required, and the query becomes simpler.
Note: In MySQL it is necessary to name derived tables, even if the name given is not intended to be used.

UNION.
Select colA, colB From TblA
UNION
Select colA, colB From TblB

Your after a left join on the first table. That will make the right side I'd he their a number (exists in both) or null (exists only in the left table )
You want
select lhs.* , rhs.id from lhs left join rhs using(Id)

Related

How to combine multiple Select queries in a single one MySql

In a webpage I want to display several tables with information.
To do that, at the moment I do
SELECT * FROM tableONE WHERE field LIKE 'criteria'
then I process the result in a foreach loop. Then I do another query to the next table and process it again
SELECT * FROM tableTWO WHERE field LIKE 'criteria'
....
SELECT * FROM tableTWENTY WHERE field LIKE 'criteria'
I've the feeling that making 20 connections with the database is suboptimal and I could make a single query and in the foreach loop put each result in the appropriate table. The issues I found to do it are:
There is no related column amongst them, so I can not do a JOIN ON.
If I do a cartesian join I get many redundant rows
I can not use UNION because the columns on each table are different.
What is the most efficient way to do this?
Thanks
I've tried JOIN, UNION and separating the tables with comas (cartesian join), but they don't give the expected result
Just use UNION Clause
SELECT field1, field2, filed3 FROM table1
UNION
SELECT field1, NULL as filed2, field4 as filed3 FROM table2
;
Beware that
Every SELECT statement within UNION must have the same number of columns
The columns must also have similar data types

empty result when using a subquery select

I have two tables (table1, table2) in a database (both with type InnoDB). They both have a column "article". In table1 "article" is the primary index, in table2 "article" is defined as "unique". Both of those columns have data type varchar(32), also the same collation.
I am trying to get a list of all "article" values which are in table1, but NOT in table2.
table1 contains about 5000 rows, table2 contains about 3000 rows, so I should get at least 2000 "article" values as a result. My query looks like this:
SELECT article FROM table1
WHERE article NOT IN
(SELECT article FROM table2);
But this returns an empty result...
When I do it the other way around (i.e. select all "article"s from table2 which are not in table1), it works, that query returns around 700 values.
I suppose this must have to do with the different index/unique status of "article" in the two tables. But how can I modify the query to get it working?
Use a left join instead. It is faster with many values anyway:
SELECT t1.article
FROM table1 t1
LEFT JOIN table2 t2 ON t1.article = t2.article
WHERE t2.article IS NULL
I just found a second solution myself (despite the accepted answer fully working): Apparently in this situation the subquery requires a WHERE clause for the whole query to work. So I added a WHERE clause that will apply to all rows in table2 (i.e. WHERE article != ""). So the complete (working) query now looks like this:
SELECT article FROM table1
WHERE article NOT IN
(SELECT article FROM table2 WHERE article != "");

MS-Access group by column having count(*) > 1 weird behavior?

I am playing around with ms-access (MS-Office Professional Plus 2013) trying to figure out if I have duplicate rows before I merge one table into another table. I want to collect the rows that are duplicates and give an error with the duplicates before the merge happens. I have two scenarios to cover. The first scenario is duplicates on a single column. The second scenario is duplicates on two columns. Any help on the first scenario would be appreciated.
Scenario 1:
The two tables have the exact same column structure so to keep it simple I will use the following table structure. ( I simply added two tables inside access and run the query to figure out the correct syntax.)
Duplicates based upon one column:
Table1 Table2
ID ID
1 1
2 3
Running the query:
Select ID from Table1
Union ALL
Select ID from Table2
group by ID having count(*) > 1
The result set is always the records from the first select statement. In other words it always returns Id=1 and Id=2. If you change Table1 to Table2 the result set is always from table2. If I change "Union all" to union same results. I tried changing the ID column names as well as change the type to be number instead of auto. Any idea what am I doing wrong?
Scenario 2: I know what the value should be in the second column so it is hard-coded. I added this here to show access appears to work as expected in this scenario but not in scenario 1.
Duplicates based upon two columns:
Table1 Table2
ID Field1 ID Field1
1 abc 1 abc
2 bcd 3 abc
Running the query below works as expected. The row with ID=1 is only returned.
select ID, Field1 from Table1 where Field1 = 'abc'
union all
select ID, Field1 from Table2 where Field1 = 'abc'
group by ID, Field1 having count(*) > 1
The GROUP BY is only being applied to the second table. You need to do the UNION ALL first, and then the GROUP BY and HAVING on a SELECT from the combined results.
Not Access specific, but something like this works:
SELECT id FROM
(
SELECT id FROM a
UNION ALL
SELECT id FROM b
) AS c
GROUP BY id HAVING COUNT(*) > 1
My preferred way to do things like that is to use the build in Query Wizard:
Query Wizard, Find Duplicates Query Wizard
Let Access create the SQL statement for you and then you can modify it and/or move it into code.

How to transfer two columns of IDs into two columns of Names using mySQL?

I have a table with two columns of IDs like this :
How do i covert it into two columns with their corresponding names using MySQL?
Without table definitions, we're just guessing:
We'll assume that the two column table is named first_table and contains columns named col1 and col2. (I resisted my Dr.Seuss-like temptation to name them thing1 and thing2.)
We'll assume that there's a second table, unfortunately named second_table, that contains columns rid and name.
We can use a query like this:
SELECT t.rid
, s.name
FROM ( SELECT t1.col1 AS rid
FROM first_table t1
UNION ALL
SELECT t2.col2
FROM first_table t2
) t
LEFT
JOIN second_table s
ON s.rid = t.rid
ORDER
BY t.rid
The inline view t gets the contents of col1 into a set, and then concatenates a second set to it, the contents of col2. This gives us a single list of values.
We wrap that query into a set of parens, to turn it into an inline view (or derived table if we use the MySQL vernacular.)
We can then do a join operation to do the lookup of name, matching on the rid column.
This isn't the only way to do it, there are other query patterns that will return an equivalent result.

Finding the intersection between two columns

I'm trying to find the (set) intersection between two columns in the same table in MySQL. I basically want to find the rows that have either a col1 element that is in the table's col2, or a col2 element that is in the table's col1.
Initially I tried:
SELECT * FROM table WHERE col1 IN (SELECT col2 FROM table)
which was syntactically valid, however the run-time is far too high. The number of rows in the table is ~300,000 and the two columns in question are not indexed. I assume the run time is either n^2 or n^3 depending on whether MySQL executes the subquery again for each element of the table or if it stores the result of the subquery temporarily.
Next I thought of taking the union of the two columns and removing distinct elements, because if an element shows up more than once in this union then it must have been present in both columns (assuming both columns contain only distinct elements).
Is there a more elegant (i.e. faster) way to find the set intersection between two columns of the same table?
SELECT t1.*
FROM table t1
INNER JOIN table t2
ON t1.col1 = t2.col2
Creating indexes on col1 and col2 would go a long way to help this query as well.
If you only want the values, try the INTERSECT command:
(SELECT col1 FROM table) INTERSECT (SELECT col2 FROM table)