I want to use a JOIN to return a boolean result. Here's an example of the data...
t1
id | data
-----------
1 | abcd
2 | 2425
3 | xyz
t2
id | data | t1_id |
-------------------------
1 | 75 | 2 |
2 | 79 | 2 |
3 | 45 | 3 |
So with these two tables I want to select all the data from t1, and also whether a given variable appears in t2.data for each id.
So say the variable is 79, the results should be
id | data | t2_boolean
--------------------------
1 | abcd | 0
2 | abcd | 1
3 | xyz | 0
So I'm thinking some sort of join is needed, but without a WHERE clause.
I've been banging my head about this one. Is it possible? I really need it inside the same statement as I want to sort results by the boolean field.
As the boolean needs to be a field, can I put a join inside of a field?
Thanks...
You might have to do a bit of work to knock this into a format suitable for MySQL but does this help?
SELECT t1.id, t1.data, t2.id IS NOT NULL AS t2_boolean
FROM t1
LEFT OUTER JOIN t2 on t1.id = t2.id AND t2.data = 79
Related
Is it possible to use LIMIT based on another column inside a subquery in MySQL? Here is a working query of what I mean.
SELECT id, name,
(SELECT AVG(value) FROM t2 WHERE t1id = t1.id ORDER BY value DESC LIMIT 4) as average
FROM t1
However I'd like to replace the "4" to a field inside t1.
Something like this where table t1 has fields id, name, size:
SELECT id, name,
(SELECT AVG(value) FROM t2 WHERE t1id = t1.id ORDER BY value DESC LIMIT t1.size) as average
FROM t1
I could join t1 and t2, but I'm not sure that works for this. Does it?
Edit:
Here's some sample data to show what I mean:
Table t1
| id | name | Size |
|----|------|------|
| 1 | Bob | 4 |
| 2 | Joe | 3 |
| 3 | Sam | 4 |
Table t2
| t1id | value |
|------|-------|
| 1 | 16 |
| 1 | 14 |
| 1 | 12 |
| 1 | 10 |
| 1 | 8 |
| 2 | 10 |
| 2 | 8 |
| 2 | 6 |
| 2 | 4 |
| 3 | 20 |
| 3 | 15 |
| 3 | 10 |
| 3 | 5 |
| 3 | 2 |
Expected result:
| id | name | avg |
|----|------|------|
| 1 | Bob | 13 |
| 2 | Joe | 8 |
| 3 | Sam | 12.5 |
Notice that the average is the average of only the top t1.size values. For example the average for Bob is 13 and not 12 (based on 4 values and not 5) and the average for Joe is 8 and not 7 (based on 3 values and not 4).
In MySQL, you have little choice other than LEFT JOIN and aggregation:
SELECT t1.id, t1.name, AVG(t2.value) as average
FROM t1 LEFT JOIN
(SELECT t2.*,
ROW_NUMBER() OVER (PARTITION BY t1id ORDER BY VALUE desc) as seqnum
FROM t2
) t2
on t2.t1id = t1.id AND seqnum <= t1.size
GROUP BY t1.id, t1.name;
Here is a db<>fiddle.
No, you cannot use a column reference in a LIMIT clause.
https://dev.mysql.com/doc/refman/8.0/en/select.html has detailed documentation about MySQL's SELECT statement including all its clauses.
It says:
The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants, with these exceptions:
Within prepared statements, LIMIT parameters can be specified using ? placeholder markers.
Within stored programs, LIMIT parameters can be specified using integer-valued routine parameters or local variables.
Expressions, including subqueries, are not mentioned as legal argument in the LIMIT clause.
A simple solution would be to do your task in two queries: the first to get the size and then use that value as a constant value in the second query that includes the LIMIT.
Not every task needs to be done in a single SQL statement.
I need an SQL code to compare data that doesn't exist in one table with respect to another table that holds the set of unique expected data.
I have tried using EXIST and NOT EXIST operators.
The EXIST operator will display all data in the second table. The NOT EXIST operator will not display any results.
The code looks something like
SELECT *
FROM st
WHERE EXISTS
(SELECT data FROM udt WHERE st.data <> udt.data)
This is my unique data table (udt) example:
+------+
| data |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
+------+
This is my second table (st) example:
+------+------+
| name | data |
+------+------+
| AZ | 1 |
| AZ | 3 |
| BY | 2 |
| BY | 4 |
| CX | 1 |
| CX | 4 |
| DW | 2 |
| DW | 3 |
+------+------+
I would like to have a code that will display the name and the code that don't exist in the second table. That is:
+------+------+
| name | data |
+------+------+
| AZ | 2 |
| AZ | 4 |
+------+------+
and so on
For one, will this be possible? If it is possible, what code syntax can I apply?
I get why EXIST and NOT EXIST will not display the data, but is there any way I can get the required results?
Not sure if this is the best way of doing this, it's still early and not much coffee yet :o)
I've changed your field names, but kept them as close as possible to yours.
select q1.[name_],q1.data1
from
(select distinct [name_],data1 from
st,udt) as q1
left join
st as d1
on q1.[name_]=d1.[name_] and
q1.data1=d1.[data_]
where d1.[name_] is null
Gives you the results
name data1
az 2
az 4
by 1
by 3
cx 2
cx 3
dw 1
dw 4
Generate all the combinations of name and data and then remove the ones that are in the second table.
In almost any database, you can do this as:
select n.name, t1.data
from (select distinct name from table2) n cross join
table1 t1 left join
table2 t2
on t2.name = n.name and t2.data = t1.data
where t2.data is null;
MS Access does not support this syntax, so you can do:
select n.name, t1.data
from (select distinct name from table2) n,
table1 t1
where not exists (select 1
from table2 t2
where t2.name = n.name and t2.data = t1.data
);
I am sure this would be easy to google if I knew the right words to use, but I've tried and not come up with anything: apologies if this is a common question on SO.
I have one table which lists a set of records which can be one of 4 types.
table_1:
+-------+------------+------+
| id | value | type |
+-------+------------+------+
| 1 | x | 1 |
| 2 | y | 1 |
| 3 | z | 2 |
| 4 | a | 3 |
+-------+------------+------+
I have another table which references the id of this table and stores data
table_2:
+-------+------------+------+
| id | table_1_id |value |
+-------+------------+------+
| 1 | 4 | A |
| 2 | 2 | B |
| 3 | 3 | C |
| 4 | 2 | D |
+-------+------------+------+
I want to write a query that effects:
"Find all the records from table 1 which are of type 1, take the id's of those records, and find all the records in table 2 where 'table_1_id' which match one of that set of ids."
In the above very oversimplified table example that would result in the query returning records with ids 2 and 4 in table 2
Sounds like your looking for IN:
select *
from table2
where table_1_id in (select id from table1 where type = 1)
Or perhaps you could JOIN the tables:
select t2.*
from table2 t2
join table1 t1 on t2.table_1_id = t1.id
where t1.type = 1
Joining the tables could result in duplicate records. Depends on your needs.
SELECT t1.value,t1.type,t2.value FROM table1 t1,table2 t2 WHERE t1.id = t2.table_1_id AND t1.type = 1;
I'm trying to get deeper into "advanced"-SQL'ing but have a slight problem with some pretty basic stuff.
I have one table, where one row refers to another row. There are of course unique id's as well but I'll skip those here:
+----------+----------------------------+
| field | name | value |
+----------+----------------------------+
| 1 | aa | 0 |
| 1 | ab | 0 |
| 2 | ba | 1 |
| 2 | bb | 1 |
| 3 | ca | 2 |
| 3 | cb | 2 |
+----------+----------------------------+
What I want to accomplish is to get field when I know field=3 and name= 'ca'.
I've tried something like this:
SELECT table.value AS parent_id FROM table WHERE table.field=3 AND table.name='ca'
That works at some point, it lists everything at 2:field, I need then to find value 1 from the field. BUT if the 2:field does not have any references (as above illustrated, 1:field) then I need the last value which will be 2:field.
How would that be possible in MySQL?
What you need is a self-join by using the same table TWICE in the same query, but different ALIAS...
select
t1.field,
t1.name,
t1.value as ThisIsYourParentKey,
t2.name as ParentName,
t2.value as GrandParentKey
from
YourTable t1
left join YourTable t2
on t1.value = t2.field
where
t1.name = 'a2'
SELECT table1.PrimaryKey(Some ID), table2.nameOfSomething
FROM table1
INNER JOIN table2
Here is the part i don't get :
USING(id)
this ID is table1 foreign key, and table2 primary key
i dont really get it..
table1.ID values:
25 Rows:
row 1-5 = 1 , row 6-10 = 2 , row 11-15 = 3 , row 16-20 = 4 , row 21-25 = 5
table2.ID values :
5 Rows:
row 1 = 1 , row 2 = 2 , row 3 = 3 , row 4 = 4 , row 5 = 5
i test it and i get different result without it, how comes?
Note : Table1 contains interests, Table2 contains categories for these interests
feel free to ask for more information
USING specifies that a join should be performed by joining on the listed columns in both tables. That is
SELECT t1.col1,
t1.col2,
t2.col1
FROM table1 AS t1
INNER JOIN table2 AS t2
USING (col1)
is the same as
SELECT t1.col1,
t1.col2,
t2.col1
FROM table1 AS t1
INNER JOIN table2 AS t2
ON t1.col1 = t2.col1
For reference, see the MySql homepage.
USING is a equi-join and relies on attribute names for the same data element remaining the same between tables.
ON is more flexible: because it requires you to explicitly specify the attribute name in both tables, attribute names for the same data element can be the same or they can be different between the tables. Also, it is a theta-join, meaning that the join type can be any condition, including equality. As a result of this flexibility, ON is more verbose.
| Table1: | Table2: |
| id | id | table1_id |
| 1 | 1 3 |
| 2 | 2 2 |
| 3 | 3 1 |
If you join the above two tables together with USING(id) it will match rows where the id value in Table1 are the same as the id value in Table2...
SELECT * FROM table1 JOIN table2 USING(id)
| id | id table1_id |
| 1 | 1 3 |
| 2 | 2 2 |
| 3 | 3 1 |
But, the id in Table2 might have nothing to do with the id in Table1. If that's the case, you can use ON to be specific about how you match records together...
SELECT * FROM table1 JOIN table2 ON table1.id = table2.table1_id
| id | id table1_id |
| 1 | 3 1 |
| 2 | 2 2 |
| 3 | 1 3 |
If you specify nothing at all, you match every record in one table, against every record in the other table...
SELECT * FROM table1 CROSS JOIN table2
| id | id table1_id |
| 1 | 1 3 |
| 1 | 2 2 |
| 1 | 3 1 |
| 2 | 1 3 |
| 2 | 2 2 |
| 2 | 3 1 |
| 3 | 1 3 |
| 3 | 2 2 |
| 3 | 3 1 |