MySQL SELECT with IF statement to set variable from another table - php

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'

Related

How to subtract values of two different columns from two different tables?

Example Table Structure
Table 1
ID | Name | Price
-----------------------------
1 | Casio | 30
2 | Titan | 40
Table 2
ID | Place | Price
-----------------------------
1 | Cali | 30
2 | Mexi | 10
Operation to perform:
Table1(Price) - Table2(Price) for ID = 1
New Table 1
ID | Name | Price
-----------------------------
1 | Casio | 0
2 | Titan | 40
ID matches in both tables
You should consider another database design to handle this case.
But to answer your question, you can create a view :
create view Differences2 as (
select t1.id, t1.price - t2.price
from t1, t2
where t1.id = t2.id
)
As you told both table will have same ID column you can use following query.
SELECT table1.ID, table1.Name, (table1.Price-table2.Price) AS Price
FROM table1
INNER JOIN table2 ON table1.ID = table2.ID
If you want to update record you can use following:
UPDATE table1
INNER JOIN table2 ON table1.ID = table2.ID
SET table1.Price = (table1.Price-table2.Price)

Selecting row from two table

please can anyone help me, I am familiar with PHP but I'm not good in it.please help. I have two table and both have id, see sample,
Table1
----------------------------------
**ID** | **NAME** | **AGE** |
----------------------------------
001 | john | 21 |
----------------------------------
002 | erik | 18 |
----------------------------------
003 | ella | 19 |
----------------------------------
and soon...
Table2
----------------------------------
**ID** | **SUBJECT** | **GRADE** |
----------------------------------
001 | math | 80 |
----------------------------------
003 | english | 83 |
----------------------------------
and soon....
here is the problem, I just want to select a row from table1 were its id dont match in table2.
I used this condition but it wont work the way I expected to so that means this is wrong,
if($t1_id!=$t2_id){
blah blah blah...
}
else
{
all data is match!
}
when an id in table2 matched in table1 it already show that my data is all match even if there is only one entry in table2.
Please help me. If you don,t understand how I show my problem please tell me,THANK YOU!.
These 2 solutions will work in sqlserver:
Solution 1:
SELECT
t1.ID, t1.NAME, t1.AGE
FROM
table1 t1
LEFT JOIN
table2 t2
ON t1.ID = t2.ID
WHERE t2.ID is null
Solution 2:
SELECT
ID, NAME, AGE
FROM
table1 t1
WHERE NOT EXISTS(SELECT * FROM table2 WHERE t1.ID = ID)
You can use exists clause to check whether a record is present in another table, e.g.
select *
from table1 t1
where t1.id = ?
and exists(
select *
from table2 t2
where t2.id = t1.id;
);

MYSQL SELECT JOIN with condition

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

How to select first row only in 2nd table of inner join query

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.

Querying according to the newest related object

I have two entities with an 1-N relation, like this :
table_a
-------
id
name
table_b
------
id
table_a_id
name
status
created_at
I'm looking for a way in MySQL and especially with Doctrine ORM to query table_a with a "where" clause on table_b that affect only the last associated table_b record.
Supposing I have the following records :
table_a
----------------------------
id | name
----------------------------
1 | john
2 | mary
3 | chuck
table_b
--------------------------------------------------
id | table_a_id | name | status | created_at
--------------------------------------------------
1 | 1 | blue | 1 | 2000-01-01
2 | 1 | red | 1 | 2012-12-31
3 | 2 | yellow | 1 | 2000-01-01
4 | 2 | green | 0 | 2012-12-31
So I want to tell MySQL/Doctrine :
GIVE ME the table_a records
WHICH HAVE table_b records
AND status = 1 ON the last related elements (according to the created_at field)
This should only return :
table_a
----------------------------
id | name
----------------------------
1 | john
According to the book SQL Antipatterns, this type of join with the proper indexes can often perform better than a subquery. So, try this method out too:
SELECT a.*
FROM table_a a
JOIN table_b b1
ON b1.table_a_id = a.id
AND b1.status = 1
LEFT JOIN table_b b2
ON b2.table_a_id = a.id
AND b2.created_at > b1.created_at
WHERE b2.table_a_id IS NULL
If there could be two rows from table_b with status 1 that have the same table_a_id and created_at date, then you will need DISTINCT to avoid duplicates:
SELECT DISTINCT a.*
FROM table_a a
JOIN table_b b1
ON b1.table_a_id = a.id
AND b1.status = 1
LEFT JOIN table_b b2
ON b2.table_a_id = a.id
AND b2.created_at > b1.created_at
WHERE b2.table_a_id IS NULL
Not sure about the "Doctrine", but a MySQL query could be
select
a.ID,
a.Name
from
table_b B
join table_a A
on B.table_a_id = A.ID
where
B.status = 1
order by
B.Created_At DESC
limit 1

Categories