I'm working on a tricky query and just don't understand how to approach it since neither JOIN gives me desirable result.
I have two tables:
Table1:
id
value
Tabel2:
id
table1_id
parameter (1,0)
value
I need to select everything from Table_1, but if there is a row in Table2 with table1_id = table1.id and parameter = 1, I want to include table2.value in the outcome. Note, that there can be multiple rows with table1_id = table1.id in Table2, but only one with parameter=1.
So, what I'm looking to get as a a result
table1.id | table1.value | table2.parameter |table2.value
1 | v1 | |
2 | v1 | 1 | v2
3 | v1 | |
4 | v1 | 1 | v2
Can someone help me with a query. Thank you for your time.
SELECT *
FROM
Table1 LEFT JOIN Table2
ON (Table1.id = Table2.table1_id AND Table2.parameter = 1)
;
You can use left join and case when for showing the table2 value
select
t1.id,
t1.value,
t2.parameter,
case when t2.table_id is not null and t2.parameter = 1 then t2.value else null end as table2_value
from table1 t1
left join table2 t2 on t2.table1_id = t1.id
Related
I want to show all the results from Table1 based on some select condition being true, and have a variable be set to 0 or 1 for each result from Table1 based on some satisfied condition with Table2.
SELECT * FROM Table1 WHERE Some_Condition=true
Foreach Table1.Name
SELECT IF(TID IS NULL, 0, 1) AS Variable FROM Table2
WHERE
Table2.Name=Table1.Name AND Table2.Val='p'
How can I make this all into one SQL call?
example call I would like to see is:
Table1:
+----+-------------------+
| ID | Name |
+----+-------------------+
| 1 | John |
+----+-------------------+
| 2 | Alan |
+----+-------------------+
Table2: So here Alan exists AND Val='p', not just existing
+-------+-----------+-----+
| TID | Name | Val |
+-------+-----------+-----+
| 1 | Alan | p |
+-------+-----------+-----+
SQL result I want from a SINGLE SELECT statement:
+------+----------+
| Name | Variable |
+------+----------+
| John | 0 |
+------+----------+
| Alan | 1 |
+------+----------+
A LEFT JOIN and a CASE statement may work for you. Please see query below.
SELECT A.Name AS item, (CASE WHEN B.Val='p' THEN 1 ELSE 0 END) AS Variable
FROM Table1 A LEFT JOIN Table2 B ON (A.Name=B.Name)
I think you just want a JOIN:
SELECT t2.Name, IF(Tt2.ID IS NULL, 0, 1) AS Variable
FROM Table2 t2 JOIN
Table1 t1
ON t2.Name = t1.Name
WHERE t2.Val = 'p' AND <some condition on t1> = true;
In MySQL, you can simplify the SELECT to:
SELECT t2.Name, (Tt2.ID IS NOT NULL) AS Variable
Note that I added the name to the SELECT, although it is not in your sample SQL.
You need LEFT JOIN Table2 to include all rows from Table1 even if row in Table2 not exists. And then in Variable column just check if Table2.TID is presented (i.e. not null).
SELECT Name, (Table2.TID IS NOT NULL) AS Variable
FROM Table1
LEFT JOIN Table2 ON Table2.Name=Table1.Name AND Table2.Val='p'
Or it can be done with IF():
SELECT Name, IF(Table2.TID IS NULL, 0, 1) AS Variable
FROM Table1
LEFT JOIN Table2 ON Table2.Name=Table1.Name AND Table2.Val='p'
How do I do this?
I have this table:
Table1
|--ID--|--Stars--|--Name--|
| 1 | 3 | Pe |
| 2 | 5 | Me |
| 3 | 7 | Fe |
|------|---------|--------|
Table2
|--ID--|--Teams--|--Age---|--Name--|
| 1 | A | 20 | Pe |
| 2 | A | 20 | Me |
| 3 | A | 20 | Pe |
|------|---------|--------|--------|
I want the sum of stars in Table1 where Name exists in Table2 and Teams=A and Age=20. (3+5=8stars)
I use this, but how do I only count the stars where the name in Table1 matches the name in Table2?
$result = mysql_query("SELECT SUM(Stars) AS starsum FROM Table1 WHERE EXISTS (select * from Table2 WHERE Teams = 'A' AND Age = '20')");
$row = mysql_fetch_assoc($result);
$antalstjernerhold = $row['starsum'];
Try this query
SELECT SUM(t1.Stars) AS starsum
FROM Table1 t1 INNER JOIN Table2 t2
ON t1.Name=t2.Name AND t2.Teams='A' AND t2.Age=20
You have to use inner join to get desired results.
You can write your query this way:
SELECT SUM(Stars) AS starsum
FROM Table1 t1
WHERE
EXISTS (
SELECT *
FROM Table2 t2
WHERE
T2.Name=T1.Name
AND T2.Teams='A'
AND t2.Age=20
)
You can use the following code
$result = mysql_query("
SELECT SUM(Stars) AS starsum
FROM Table1
WHERE Name IN (
SELECT DISTINCT t1.Name
FROM Table1 t1, Table2 t2
WHERE t1.Name = t2.Name
AND t2.Teams = 'A'
AND t2.Age = 20
)
");
$row = mysql_fetch_assoc($result);
$antalstjernerhold = $row['starsum'];
The query is using below subquery which will fetch the names belonging to both tables and have teams as A and Age 20 & then using those names we get the sum of stars
SELECT DISTINCT t1.Name
FROM Table1 t1, Table2 t2
WHERE t1.Name = t2.Name
AND t2.Teams = 'A'
AND t2.Age = 20
I'm using the following query to select data from 3 different tables. tbl_invoices and tbl_clients have unique records. Each tbl_invoices record has multiple tbl_invoice_entries records:
$query = 'SELECT T1.*, T2.*, T3.*
FROM tbl_invoices T1
LEFT JOIN tbl_invoice_entries T2
ON T1.number = T2.invoice_number
LEFT JOIN tbl_clients T3
ON T1.client = T3.client_id
WHERE date_format(date, '%Y') = ".$_POST['year']." AND date_format(date, '%c') = ".$_POST['month']." ORDER BY date, number ASC'
$stmt = $conn->prepare($query)
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
This currently returns all records in tbl_invoice_entries. How do I change my query in order to only return the first tbl_invoice_entries record for each tbl_invoices record.
Here are the tables:
tbl_clients
+----+-----------+----------+
| id | firstname | lastname |
+----+-----------+----------+
| 1 | John | Doe |
| 2 | Jane | Doe |
+----+-----------+----------+
tbl_invoices
+----+--------+--------+------------+
| id | number | client | date |
+----+--------+--------+------------+
| 1 | 14 | 1 | 2015-07-14 |
| 1 | 15 | 2 | 2015-07-14 |
+----+--------+--------+------------+
tbl_invoice_entries
+----+----------------+------------+
| id | invoice_number | produkt |
+----+----------------+------------+
| 1 | 14 | Fish |
| 2 | 14 | Bread |
| 3 | 15 | Vegetables |
| 4 | 15 | Fruit |
+----+----------------+------------+
So the results I'm looking for are:
John Doe 14 Fish 2015-07-14
Jane Doe 15 Vegetables 2015-07-14
Thanks for any help!
By linking the invoice_entries table not directly through the invoice number but by the id of its first entry you can achieve what you want:
SELECT firstname,lastname,number,product,date
FROM tbl_invoices T1
LEFT JOIN tbl_invoice_entries T2
ON T2.id =(select min(id) from tbl_invoice_entries
where invoice_number=number)
LEFT JOIN tbl_clients T3
ON T1.client = T3.id
WHERE ...
You need to tell the RDBMS what you intend by the first row. There is no natural order in tuples. If you want the tuple with lowest ID given the same invoice_number, then it would require another query
SELECT tbl1.* FROM tbl_invoice_entries AS tbl1
JOIN ( SELECT MIN(id) AS id, invoice_number FROM tbl_invoice_entries
GROUP BY invoice_number ) AS tbl2
USING (id);
The above query is equivalent to tbl_invoice_entries but only has the lowest ID of each invoice number. You can do it as a VIEW (actually two, since you can't use subqueries in a VIEW):
CREATE VIEW tbl_invoice_entries_firstnumber AS
SELECT MIN(id) AS id, invoice_number
FROM tbl_invoice_entries
GROUP BY invoice_number;
CREATE VIEW tbl_invoice_entries_first AS
SELECT tbl1.* FROM tbl_invoice_entries AS tbl1
JOIN tbl_invoice_entries_firstnumber
USING (id);
After that you can use tbl_invoice_entries_first instead of tbl_invoice_entries in your current query.
Keep in mind that the view is dynamic, so it is only a shorthand for a more complex query. This means that your current query will become more complicated and require a longer time:
SELECT T1.*, T2.*, T3.*
FROM tbl_invoices AS T1
LEFT JOIN tbl_invoice_entries_first AS T2
ON T1.number = T2.invoice_number
LEFT JOIN tbl_clients AS T3
ON T1.client = T3.id; -- you have no client_id in T3
I have set up a fiddle here.
Or you can modify your query more, and add a JOIN condition on T2 so that it only fetches, again, the minimum ID - or whatever ordering condition you prefer:
SELECT T1.*, T2.*, T3.*
FROM tbl_invoices AS T1
LEFT JOIN tbl_invoice_entries AS T2
ON (
-- (( T1.number = T2.invoice_number AND )) --
T2.id = (
SELECT MIN(id) FROM tbl_invoice_entries
WHERE invoice_number = number
))
LEFT JOIN tbl_clients AS T3
ON T1.client = T3.id;
UPDATE: The check on number was commented out (see also #cars10's solution) because it is carried over by the inner subquery.
Finally you can do this in code, i.e. you save the value of the previous tuple and order the query as needed; then discard all unneeded tuples. If you have few entries per invoice, this might be worthwhile:
// pseudo code
if (prev.client == tuple.client)
and
(prev.invoice == tuple.invoice)
continue;
prev = tuple;
-- use tuple.
I have three tables with same structure.
table1
id | email | count
1 | test1#abc.com | 5
2 | test2#abc.com | 5
3 | test3#abc.com | 5
table2
id | email | count
1 | test1#abc.com | 50
2 | test1#abc.com | 50
3 | test3#abc.com | 50
table3
id | email | count
1 | test1#abc.com | 40
2 | test1#abc.com | 45
3 | test1#abc.com | 50
Now what i want is for table1, for first record "test1#abc.com", I need sum of "count" field of next two tables. So i used below query
SELECT (IFNULL(sum(distinct(table2.count)), 0) +
IFNULL(sum(distinct(table3.count)), 0)) as total
FROM table1
LEFT JOIN table2 ON table1.email = table2.email
LEFT JOIN table3 ON table1.email = table3.email
WHERE table1.email = 'test1#abc.com'
This query gives me below record:
185
But the result should be as below:
235
This is because i have used distinct when adding field. But if i don't use distinct, it gives me 285.
Please help. What should i do?
Your issue is because, first, you're using LEFT JOIN (no sense with summation since NULL-records will provide nothing), second, that's how JOIN works. Illustrate with query:
SELECT
t1.id AS id_1,
t1.email AS email_1,
t1.count AS count_1,
t2.id AS id_2,
t2.email AS email_2,
t2.count AS count_2,
t3.id AS id_3,
t3.email AS email_3,
t3.count AS count_3
FROM
table1 AS t1
INNER JOIN table2 AS t2 ON t1.email=t2.email
INNER JOIN table3 AS t3 ON t1.email=t3.email
WHERE
t1.email='test1#abc.com'
(fiddle is here). As you can see, you'll get repeated id's from second and third tables - and - yes, that's because there are multiple rows for joining condition.
To resolve your issue you may add distinction by id into join (and later filtering that with variables or like that), but I would not recommend it. JOIN is simply not the thing for your issue. Use UNION, like:
SELECT
SUM(`count`) AS s
FROM
(
SELECT
table2.count
FROM
table2
WHERE
email='test1#abc.com'
UNION ALL
SELECT
table3.count
FROM
table3
WHERE
email='test1#abc.com'
) AS u
(see the fiddle)
I have a database that looks like:
TABLE 1
ID | NAME | PRICE
TABLE 2
TABLE1.ID | ITEM
As you can see it is possible that table 2 can contain multiple references to table 1.
Is it possible to create a query that gives a result like this?
TABLE1.ID | NAME | PRICE | TABLE2.ITEM REC 1 | TABLE2.ITEM REC 2 | TABLE2.ITEM REC 3
Consider looking at this MySQL function: GROUP_CONCAT(expr). It will sure answer your question
Mysql Documentation - group_concat()
Try this one:
SELECT t1.*, GROUP_CONCAT(t2.ITEM) AS Items
FROM Table1 t1
JOIN Table2 t2
ON t1.ID = t2.TABLE1_ID
GROUP BY t1.ID
See this SQLFiddle