I get problem with query Mysql. I have 2 tables like at picture , and I want get result like at picture too...
how the query with UNION ? thanks .. sorry for my english
You can get this result with a LEFT JOIN:
SELECT
b.date_b as date_all,
a.quota_a,
b.quota_b
FROM
tabel_b b
LEFT JOIN
tabel_a a
ON
a.id_a = b.id_b
You've got to take the date info from tabel_b, because else you get a NULL value for id = 4.
Demo
If tabel_a can have more rows than tabel_b too, then you've got to use a FULL OUTER JOIN. Because MySQL hasn't got inbuild FULL OUTER JOIN you can emulate this by a UNION of a LEFT JOIN and a RIGHT JOIN. And as Strawberry has pointed out, maybe is the equality of the id columns the result of simplification. I add therefor the equality of the date columns to the join condition:
Please regard that you've got to use UNION, not UNION ALL to get only distinct rows.
SELECT
b.date_b as date_all,
a.quota_a,
b.quota_b
FROM
tabel_b b
LEFT JOIN
tabel_a a
ON
a.id_a = b.id_b
AND
a.date_a = b.date_b
UNION
SELECT
b.date_b as date_all,
a.quota_a,
b.quota_b
FROM
tabel_a a
LEFT JOIN
tabel_b b
ON
a.id_a = b.id_b
AND
a.date_a = b.date_b
Demo (Note: with the sample data gets this the same result as the first one).
if date is the parameter that "link" your tables [foreign key?] (from your answer title it seems), you could write the following query
SELECT date_a AS date_all, quota_a, quota_b
FROM tabel_B LEFT JOIN tabel_A ON date_a = date_b
ORDER BY date_all ASC
that way you'll obtain every record in tabel_b: if they have a corrispondence in tabel_a, either date_a and date_b will have a value, otherwise date_a will be null.
Please, pay attention: in that way you'll not obtain records that are present in tabel_a but not in tabel_b
Related
I am trying to create an SQL query, but when I left join an additional table (c) with conditions it reduces the number of rows.
SELECT a.id, a.naziv as nazivOperacije, b.NNaziv as nazivArtikla, b.sifra as sifraArtikla,
norma, idArtikla
FROM artikli_rad a
LEFT JOIN artikli b ON a.idArtikla = b.id
ORDER BY a.idArtikla ASC
Query below works great. I would like to keep the records I get, but I would like to JOIN another table. Once I do that it reduces number of rows.
SELECT a.id, a.naziv as nazivOperacije, b.Naziv as nazivArtikla, b.sifra as sifraArtikla,
norma, idArtikla, sum(c.kolicina) as kolRadnogNaloga
FROM artikli_rad a
LEFT JOIN artikli b ON a.idArtikla = b.Id
LEFT JOIN radni_nalozi c ON a.idArtikla = c.idArtikal
WHERE c.status = 1
ORDER BY a.idArtikla ASC
How I can show all rows from first query and attach table radni_nalozi c with where condition that sums only quantity with status = 1?
try this
With Outer Join, if you put in where clause then it will be treated as inner join.
$stmt = "SELECT a.id, a.naziv as nazivOperacije, b.Naziv as nazivArtikla, b.sifra as sifraArtikla, norma, idArtikla, sum(c.kolicina) as kolRadnogNaloga
FROM artikli_rad a
LEFT JOIN artikli b ON a.idArtikla = b.Id
LEFTJOIN radni_nalozi c ON a.idArtikla = c.idArtikal and c.status = 1
ORDER BY a.idArtikla ASC";
You outer-join radni_nalozi. This means that in case there is no match, the original row is kept and all radni_nalozi columns are null. Then you limit your results by:
WHERE c.status = 1
This dismisses all outer-joined rows, because their status is null. You have turned your outer join into an inner join.
What you want instead is the condition to be part of the join clause:
LEFT JOIN radni_nalozi c ON a.idArtikla = c.idArtikal AND c.status = 1
But as P.Salmon just pointed out, your query is invalid, because of a malformed aggregation. MySQL should raise a syntax error, but obviously you have not SET sql_mode = 'ONLY_FULL_GROUP_BY', which you should in order to have the DBMS prevent you from writing such invalid queries. With sum(c.kolicina) and no GROUP BY clause, you tell the DBMS to limit your results to a single row containing the sum. But what values for a.id, a.naziv, etc. is the DBMS supposed to show then?
It seems you want to join the radni_nalozi sums:
SELECT
ar.id,
ar.naziv as nazivOperacije,
a.Naziv as nazivArtikla,
a.sifra as sifraArtikla,
a.norma,
ar.idArtikla,
rn.sum_kolicina AS kolRadnogNaloga
FROM artikli_rad ar
JOIN artikli a ON a.id = ar.idArtikla
LEFT JOIN
(
SELECT idArtikal, SUM(kolicina) AS sum_kolicina
FROM radni_nalozi
WHERE status = 1
GROUP BY idArtikal
) rn ON rn.idArtikla = ar.idArtikal
ORDER BY ar.idArtikla ASC;
I have also used mnemonic alias names. names like a, b, and c don't make the query more readable as alias names are supposed to do, but make it less readable.
I also turned the outer join on artikli into an inner join, because there must be no artikli_rad row without a match in artikli in a properly set up database.
I am running a SELECT query to return addresses in a table associated with a certain "applicant code" and I'd like to join a table to also return (in the same row) the name of that applicant.
Therefore my query as of now is
SELECT a.id, a.created_at, a.updated_at, a.code, a.applicant_code, a.form_code, a.address_line_1, a.address_line_2, a.town_city, a.county_state, a.country, a.post_code, a.start_date, a.end_date, a.type, ap.first_name, ap.last_name
FROM sfs_addresses a
JOIN sfs_personal_details ap ON a.form_code = ap.form_code
WHERE a.form_code = ? AND a.applicant_code = ?
The query works, and I get the right columns and values in each row, but it returns 2 of each so like
ID
===
1
1
2
2
3
3
4
4
If I remove the JOIN it works fine. I have tried adding DISTINCT (makes no difference) I'm lost.
EDIT: Based on this answer and the comments, the OP realized that the JOIN condition should be on applicant_code rather than form_code.
You have duplicates in the second table based on the JOIN key you are using (I question if the JOIN is correct).
If you just want one row arbitrarily, you can use row_number():
SELECT a.*, ap.first_name, ap.last_name
FROM sfs_addresses a JOIN
(SELECT ap.*,
ROW_NUMBER() OVER (PARTITION BY ap.form_code ORDER BY ap.form_code) as seqnum
FROM sfs_personal_details ap
) ap
ON a.form_code = ap.form_code
WHERE a.form_code = ? AND a.applicant_code = ?;
You can replace the columns in the ORDER BY with which result you want -- for instance the oldest or most recent.
Note: form_code seems like an odd JOIN column for a table called "personal details". So, you might just need to fix the JOIN condition.
relation between 2 tables one to many to return non duplicate use distinct
SELECT distinct a.id, a.created_at, a.updated_at, a.code, a.applicant_code, a.form_code, a.address_line_1, a.address_line_2, a.town_city, a.county_state, a.country, a.post_code, a.start_date, a.end_date, a.type, ap.first_name, ap.last_name
FROM sfs_addresses a
JOIN sfs_personal_details ap ON a.form_code = ap.form_code
WHERE a.form_code = ? AND a.applicant_code = ?
I am stuck with implementing the below requirement.kindly please help me to fix this query
The requirement
The condition needs to be implemented in theory
Need to populate data for market_num in "demo" table from either "table1" or "table2" table based on "source_country_palce" column in "demo" table.
It shall be picked from "table1" if present there else need to pick from "table2".I am stuck with writing the condition.Kindly please help me to fix this
Query tried so for
condition 1
select distinct b.market_num
from test.demo a
join test.table1 b on a.source_country_palce = b.market_palce
where b.market_num >=1
condition 2
select distinct b.market_num
from test.demo a
join test.table2 b on a.source_country_palce = b.country_palce
where b.market_num >=1
But I am stuck with implementing the above condition like when the 1st condition fails then I need to pick "market_num" from the second condition
My pure guess:
select distinct coalesce(b.market_num,c.market_num )
from test.demo a left outer join test.table1 b
on a.source_country_palce=b.market_palce
left outer join test.table2 c
on a.source_country_palce=c.country_palce
where b.market_num >=1 or c.market_num >=1 ;
You can try this:
SELECT DISTINCT COALESCE(b.market_num, c.market_num)
FROM test.demo a
LEFT JOIN test.table1 b ON a.source_country_palce = b.market_palce
AND b.market_num >= 1
LEFT JOIN test.table2 c ON a.source_country_palce = d.country_palce
AND b.market_num < 1
AND c.market_num >= 1
I put your conditions in the join in a way that it will only match if the second join if it fails the first one.
I am trying to display some info merging 4 tables. My tables are device, device_model, sub_product_area and borrow_device.
The problem I have is, when I link the tables to device table using a LEFT JOIN there are some duplicates for the transaction_ID from the borrow_device table. So I want to ORDER BY on transaction_Mode ONLY for that LEFT JOIN and only take the 'red' color relevant transaction_ID at such instances. I have tried SELECT DISTINCT but it didn't work. None of the similar question answers worked.
Here is my query ->
SELECT *
FROM device b
LEFT OUTER JOIN device_model a ON (b.`model_ID`=a.`model_ID`)
LEFT JOIN sub_product_area c ON (b.`sub_Product_Area_ID` = c.`sub_Product_Area_ID`)
LEFT JOIN borrow_device d ON (d.`device_ID` = b.`device_ID` and CURDATE() between from_Date and to_Date)
ORDER BY d.transaction_Mode DESC
My table structures are as below -:
Thanks in advance!
Adding a 'GROUP BY' to the end solved my problem. Thanks everyone!
device table and sub_product_area table have 2 field related are sub_product_area_id and product_area_id. in your SQl statement try to add "and b.product_Area_ID = c.product_Area_ID", so your syntax would be like this bellow :
SELECT *
FROM device b
LEFT OUTER JOIN device_model a ON (b.`model_ID`=a.`model_ID`)
LEFT JOIN sub_product_area c ON (b.`sub_Product_Area_ID` = c.`sub_Product_Area_ID` and b.`product_Area_ID` = c.`product_Area_ID`)
LEFT JOIN borrow_device d ON (d.`device_ID` = b.`device_ID` and CURDATE() between from_Date and to_Date)
ORDER BY d.transaction_Mode DESC
i have 2 tables
1 - coupons
2 - tractions
for each coupon there might be couple of rows in tractions table
i want to have list of all coupons and count of it's tractions (void ones in this example)
SELECT `coupons`.*, count(tractions_void.id) as void
FROM `coupons`
LEFT JOIN `tractions` AS `tractions_void`
ON `tractions_void`.`coupon_parent` = `coupons`.`id`
AND `tractions_void`.`expired` = 1
WHERE `coupons`.`parent` =0
the problem is even though i use left join , in the output i only get coupons with at least 1 tractions .... basically i dont get the coupons with 0 tractions in the query result at all
i want to have them with 0 as tractions_void ... i thought if i use left join i wont have this problem ?
You need a group by clause:
SELECT c.*, count(t.id) as void
FROM coupons c LEFT JOIN
tractions t
ON t.coupon_parent = c.id AND
t.expired = 1
WHERE c.parent = 0
group by c.id;
I also replaced the table names with shorter aliases and removed the backticks to make the query more readable.
Your original query only returned one row, because it had an aggregation function in the select clause and no group by clause.
use this
SELECT `coupons`.*, count(tractions_void.id) as void
FROM `coupons`
LEFT JOIN `tractions` AS `tractions_void`
ON `tractions_void`.`coupon_parent` = `coupons`.`id`
WHERE `coupons`.`parent` =0
AND `tractions_void`.`expired` = 1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----moved this here in where clause