How to join elements with condition? - sql

I have two tables: regions and regions_access_purchases.
I need a way to generate for user result table that have info about his current active purchase (access to region).
If user have no any purchased/accessed region he should get full list of regions.
If he have some purchased regions he should get full regions list with appended from right column about his purchaseEndDate.
I tried different joins, but all of them do not work:
SELECT region_id, translite_name, "purchaseEndDate" FROM regions
FULL OUTER JOIN regions_access_purchases reg_purch ON regions.id = reg_purch.region_id
WHERE user_id = 1 AND
"purchaseEndDate" > now()
I am getting only two regions, but I need to get full list of regions, with column from right with "purchaseEndDate". If "purchaseEndDate" is less than now it should not present, but region should be displayed in list.
Is it's possible to do such join?
http://sqlfiddle.com/#!15/30e72/2

If you move condition from WHERE to FROM statement and change FULL JOIN to LEFT JOIN you will get expected result:
SELECT * FROM regions
LEFT JOIN regions_access_purchases reg_purch ON regions.id = reg_purch.region_id AND user_id = 1 AND "purchaseEndDate" > now()
P.S. Not sure if you need to add purchaseEndDate to query, added it as you had it in your example.

Related

How do I run a SQL query against 2 views that are linked by an ID but has different column names?

I currently have 2 views that house some data.
View1: includes patientsPID and their billing/invoice information (high-level)
View2: includes patientsCID and their respective line items for their billing invoice information (granularity of View1)
I am trying to run a query where I will be able to validate some data. E.g. -> I want to see patientsPID = 1 and see the total amount paid and join it to View2 to see in more details on the invoice.
expected results
Thank you.
You need to join View1 and View2:
select v1.patientspid, v1.invoiceheader, v2.invoiceline, v2.amount
from view1 v1 inner join view2 v2
on v1.patientspid = v2.patientscid
order by v1.patientspid
If you want to get the results for a patientspid use
where v1.patientspid = 1
and no order by
In this case both PatientsPID and PatientsCID act as your Key. The column names don't have to be the same as long as the data contained in them are linked (Same Data).
Select View1.PatientsPID, View1.AmountPaid, View2.[SomeColumnName]
From View1 inner join View2 on View1.PatientsPID = View2.PatientsCID
Where View1.PatientsPID = 1
Use Join in the From line and you have to set which columns are equal between the two tables. These columns have to contain the same data in order to be able to link. Whatever column names you want to select just place the table name in front of it as show above, this prevents errors in the event of an ambiguous column name

Access SQL query without duplicate results

I made a query and wanted to not have any duplicates but i got some times 3 duplicates and when i used DISTINCT or DISTINCTROW i got only 2 duplicates.
SELECT f.flight_code,
f.status,
a.airport_name,
a1.airport_name,
f.departing_date+f.departing_time AS SupposedDepartingTime,
f.landing_date+f.landing_time AS SupposedLandingTime,
de.actual_takeoff_date+de.actual_takeoff_time AS ActualDepartingTime,
SupposedLandingTime+(ActualDepartingTime-SupposedDepartingTime) AS ActualLandingTime
FROM
(((Flights AS f
LEFT JOIN Aireports AS a
ON a.airport_code = f.depart_ap)
LEFT JOIN Aireports AS a1
ON f.target_ap = a1.airport_code)
LEFT JOIN Irregular_Events AS ie
ON f.flight_code = ie.flight_code)
LEFT JOIN Delay_Event AS de
ON ie.IE_code = de.delay_code;
had to use LEFT JOIN because when i used INNER JOIN i missed some of the things i wanted to show because i wanted to see all the flights and not only the flights that got delayed or canceled.
This is the results when i used INNER JOIN, you can see only the flights that have the status "ביטול" or "עיכוב" and that is not what i wanted.
[the results with LEFT JOIN][2]
[2]: https://i.stack.imgur.com/cgE2G.png
and when i used DISTINCT where you see the rows with the NUMBER 6 on the first column it appear only two times
IMPORTANT!
I just checked my query and all the tables i use there and i saw my problem but dont know how to fix it!
in the table Irregular_Events i have more the one event for flights 3,6 and 8 and that is why when i use LEFT JOIN i see more even thou i use distinct, please give me some help!
Not entirely sure without seeing the table structure, but this might work:
SELECT f.flight_code,
f.status,
a.airport_name,
a1.airport_name,
f.departing_date+f.departing_time AS SupposedDepartingTime,
f.landing_date+f.landing_time AS SupposedLandingTime,
de.actual_takeoff_date+de.actual_takeoff_time AS ActualDepartingTime,
SupposedLandingTime+(ActualDepartingTime-SupposedDepartingTime) AS ActualLandingTime
FROM
((Flights AS f
LEFT JOIN Aireports AS a
ON a.airport_code = f.depart_ap)
LEFT JOIN Aireports AS a1
ON f.target_ap = a1.airport_code)
LEFT JOIN
(
SELECT
ie.flight_code,
de1.actual_takeoff_date,
de1.actual_takeoff_time
FROM
Irregular_Events ie
INNER JOIN Event AS de1
ON ie.IE_code = de1.delay_code
) AS de
ON f.flight_code = de.flight_code
It is hard to tell what is the problem with your query without any sample of the output, and without any description of the structure of your tables.
But your problem is that your are querying from the flights table, which [I assume] can be linked to multiple irregular_events, which can possibly also be linked to multiple delay_event.
If you want to get only one row per flight, you need to make sure your joins return only one row too. Maybe you can do it by adding one more condition to the join, or by adding a condition in a sub-query.
EDIT
You could try to add a GROUP BY to the query:
GROUP BY
f.flight_code,
f.status,
a.airport_name,
a1.airport_name;

Left/Right join table with itself

I have a table which contains all the active loans for every month (for example 2017_01, 2017_02, 2017_03, etc). As I don't have another table which contains the Non Active loans (the closed ones) I have to manipulate the same table to get the closed loans for every specific months.
I have tried RIGHT OUTER JOIN in order to get the loans which are part of the previous YEAR_MONTH and have a NULL value in the next month, but as the table is joining itself using the LOAN_NUMBER field as a key, I am not getting the desired results.
Any idea of what I can do?
Ps: In other cases I needed to do that I used the "WHERE NOT EXISTS" clause, but I had two different tables.
My query is:
SELECT DM07MD.LOAN_NUMBER, DM07MD2.LOAN_NUMBER AS L2
FROM [dbo].[DM_07MONTHLY_DATA] DM07MD
LEFT OUTER JOIN [dbo].[DM_07MONTHLY_DATA] DM07MD2
ON DM07MD.LOAN_NUMBER = DM07MD2.LOAN_NUMBER
AND DM07MD.YYYY_MM = '2017_01'
WHERE DM07MD.S90T01_CLIENT_SEGMENT IN ('PI', 'MICRO')
AND DM07MD.S90T01_IS_RESTRUCTURED = 1
AND DM07MD2.LOAN_NUMBER IS NULL
AND DM07MD.YYYY_MM = '2017_02'
You can get the same by using exists,
SELECT DM07MD.LOAN_NUMBER FROM [dbo].[DM_07MONTHLY_DATA] DM07MD where DM07MD.YYYY_MM = '2017_02' and not exists
( SELECT 1 FROM [dbo].[DM_07MONTHLY_DATA] DM07MD2 where DM07MD.YYYY_MM = '2017_01' and DM07MD.LOAN_NUMBER=DM07MD2.LOAN_NUMBER )

How to return 1st record from group by

Trying to return only the 1st supplier code and have all other fields unaffected.
`Select
Container.Part_Key,
Part.Part_No,
Part.Name,
Part.Revision,
Container.Quantity,
Container.Container_Status,
OP.Operation_No,
Opp.Operation_Code,
Part.Part_Status,
Supplier.Supplier_Code
From Part_v_Container as Container
Join Part_v_Part as Part
ON Part.Part_Key = Container.Part_Key
Join Part_v_Part_Operation as Op
On Op.Part_Operation_Key = Container.Part_Operation_Key
Join Part_v_Operation as OPP
On OPP.Operation_Key = OP.Operation_Key
Join part_v_approved_supplier as Approved
On Approved.part_key = container.part_key
Join common_v_Supplier as Supplier
On Supplier.supplier_no = Approved.Supplier_No
Where Container.Active = '1'
group by container.part_key`
There will be duplicate part numbers, revisions, etc. Not worried about that. I just want the part no to list only one approved supplier to the far right, even though for any given part, there are multiple approved suppliers listed in the database.
Furthermore, the order the database lists the approved suppliers does not matter.
Thanks!
Add a sub query in your select list
( select top 1 supplier.supplier_code
From supplier
Where Supplier.supplier_no = Approved.Supplier_No order by Supplier.supplier_no) as supplier code
This can be the last field in the select list
You could add An appropriate order by.
This would work in SQL Server

Join distant SQL tables without pulling data in between

I have two mySQL tables that are distantly related: Box and Schedule.
The tables are only related through many other table joins.
A box has a subscription ID, a subscription has a boxContent ID and a boxContent has a Schedule ID.
Many boxes have one subscription
One Subscription has many boxContents
Many boxContents have one Schedule
I need to get all of the Schedule details attached to boxes and group them by the delivery date of the boxes.
The problem I have, is that I cannot figure out how to group them, or join them, so that the subscription and boxcontents data doesnt fill the results up with invalid results.
For example:
SELECT
Box.expected_delivery_date, count(Box.id) num_boxes
FROM
Box
WHERE
Box.state = 3 AND Box.status = 2
GROUP BY Box.expected_delivery_date;
returns the correct amount of boxes that I need to look for:
2010-10-01 - 2
2010-10-07 - 4
However, when I include the tables I need to link the two together, I get all of their data confusing the results
SELECT
Box.expected_delivery_date, count(Box.id) num_boxes
FROM
Box
JOIN
Subscription ON Box.subscription_id = Subscription.id
JOIN
BoxContent ON Subscription.id = BoxContent.subscription_id
JOIN
Schedule ON Schedule.id = BoxContent.schedule_id
WHERE
Box.state = 3 AND Box.status = 2
GROUP BY Box.expected_delivery_date;
Returns:
2010-10-01 - 10
2010-10-07 - 17
Im sure there is a simple way to do this, Im just not great at SQL.
Use DISTINCT to count the distinct Box.id in your query -
SELECT
Box.expected_delivery_date, count(DISTINCT Box.id) num_boxes
FROM
Box
JOIN
Subscription ON Box.subscription_id = Subscription.id
JOIN
BoxContent ON Subscription.id = BoxContent.subscription_id
JOIN
Schedule ON Schedule.id = BoxContent.schedule_id
WHERE
Box.state = 3 AND Box.status = 2
GROUP BY Box.expected_delivery_date;
This should return
2010-10-01 - 2
2010-10-07 - 4
Similarly, when you JOIN box with subscription, content, schedule tables you will get many duplicates. You need to analyze the data and see how you need to GROUP BY.
Use this query to see the actual data used by the query before grouping and decide on which columns to group by. Mostly, it will be the columns where you see duplicate data in multiple rows.
SELECT
Box.expected_delivery_date, Box.id BoxID, Schedule.id SchID
FROM
Box
JOIN
Subscription ON Box.subscription_id = Subscription.id
JOIN
BoxContent ON Subscription.id = BoxContent.subscription_id
JOIN
Schedule ON Schedule.id = BoxContent.schedule_id
WHERE
Box.state = 3 AND Box.status = 2
You may even try SELECT Box.*, Schedule.* in above query to come up with a final grouping.
If you need any more specific answer, you will have to provide the dummy data for all those table and the result you are looking for.
I would agree with the comments and try using DISTINCT. This should filter out the duplicate rows you would be getting by joining your "middle" tables.