Merge 2 columns from different SQL server table with empty lines - sql

I have this query to achieve my goal:
SELECT
Datum, LeavetypeID
FROM
Kalender
INNER JOIN
VerlofLijn ON Kalender.ID = VerlofLijn.DagID
WHERE
VerlofLijn.Persnummer = #pnummer;
So basically I have a calendar in the table Kalender.
Every day has a unique id(Kalender.ID). In a second table (VerlofLijn) the matching Kalender.ID is stored in VerlofLijn.DagID, together with the leavetype and the unique employee number Persnummer.
What I want to achieve is a query that loads all dates from the calendar, and - if the current logged-on employee has leave in the database - show this next to the correct date.
So if there is no leave at all in the database for this employee, I still need the calendar to show up so in a next step he can add leave to his personal calendar.
I could create a personal calendar for every employee, but there has to be a better way, without the overhead of storing way to much data in the database, which will make the query to take much more time to search and complete.

Please try this query
SELECT
Datum, LeavetypeID
FROM
Kalender
LEFT JOIN
VerlofLijn
ON Kalender.ID = VerlofLijn.DagID AND VerlofLijn.Persnummer = #pnummer;
Explanation: As you mentioned
i want to achieve is a query that loads all dates from the calendar
you should use Kalender LEFT JOIN VerlofLijn

Have you tried LEFT OUTER JOIN like this?
SELECT
Datum, LeavetypeID
FROM
Kalender
LEFT OUTER JOIN
VerlofLijn ON Kalender.ID = VerlofLijn.DagID
WHERE
VerlofLijn.Persnummer = #pnummer;
You get all the values from Kalendar even if there are no matches from the table VerlofLijn, and all the common values from VerlofLijn.
You can find some examples here: What is the difference between "INNER JOIN" and "OUTER JOIN"?

Related

Joining two views on id AND date not working

Situation thus far
I have two tables sales_orders and purchase_orders which contain id, company_id and inserted_at each.
I created two views sales_orders_view and purchase_orders_view which truncate the timestamp to that week's monday (using the date_trunc function) and count the orders entered by each company. So my sales_order_view and purchase_order_view look like this:
What I am trying to accomplish
I am trying to join the two views to create a data set which looks as follows:
This is what I am doing:
SELECT
so.company_id,
so.week_of,
so.sales_orders,
po.purchase_orders
FROM
sales_orders_view so
INNER JOIN
purchases_orders_view po
ON so.company_id = po.company_id
GROUP BY
so.company_id,
so.week_of,
sales_orders,
purchase_orders
The numbers I get back as a result are completely out of whack and I can't figure out for the life of me what I am doing wrong.
Would really appreciate some help.
Thanks!
No aggregation is needed. Just include the week in the ON clause:
SELECT so.company_id, so.week_of, so.sales_orders,
po.purchase_orders
FROM sales_orders_view so INNER JOIN
purchases_orders_view po
ON so.company_id = po.company_id AND so.week_of = po.week_of;
Note: This only returns weeks that are in both tables for a given company. If you want all weeks where there are no matches, then you need an outer join of some sort.

Record with latest date, where date comes from a joined table

I have tried every answer that I have found to finding the last record, and I have failed in getting a successful result. I currently have a query that lists active trailers. I am needing it to only show a single row for each trailer entry, where that row is based on a date in a joined table.
I have tables
trailer, company, equipment_group, movement, stop
In order to connect trailer to stop (which is where the date is), i have to join it to equipment group, which joins to movement, which then joins to stop.
I have tried using MAX and GROUP BY, and PARTITION BY, both of which error out.
I have tried many solutions here, as well as these
https://thoughtbot.com/blog/ordering-within-a-sql-group-by-clause
https://www.geeksengine.com/article/get-single-record-from-duplicates.html
It seems that all of these solutions have the date in the same table as the thing that they want to group by, which I do not.
SELECT
trailer.*
company.name,
equipment_group.currentmovement_id,
equipment_group.company_id,
movement.dest_stop_id, stop.location_id,
stop.*
FROM trailer
LEFT OUTER JOIN company ON (company.id = trailer.company_id)
LEFT OUTER JOIN equipment_group ON (equipment_group.id =
trailer.currenteqpgrpid)
LEFT OUTER JOIN movement ON (movement.id =
equipment_group.currentmovement_id)
LEFT OUTER JOIN stop ON (stop.id = movement.dest_stop_id)
WHERE trailer.is_active = 'A'
Using MAX and GROUP BY gives error "invalid in the select list... not contained in...aggregate function"
Welllllll, I never did end up figuring that out, but if I joined movements on to equipment group by two conditions, all is well. Each extra record was created by each company id.... company id is in EVERY table.

join to all rows of a table even without values sql server

I have a date table that I use to determine week of the year (our year is not calendar year based right now.). I have a union query that creates a table that I am going to use in a table valued function. I can create the table in the union query but it only produces the 40 weeks that have actual data. I need it to show the weeks regardless of whether data exists or not.
I have tried to left outer join on the week table but I still get only records where the week has data associated with it.
left outer join [dbo].[LOOKUP_WEEK_NUMBER] w on
(p.[Program_Year_ID] = w.[Program_Year_Nbr]) and
(p.[Installation_Complete_Date] between w.[Week_Start] and w.[Week_End])
LOOKUP_WEEK_NUMBER table has all the weeks of the year and a start and end date for each week. The p table contains the project data. What I am doing is bucketing the projects into weeks for reporting purposes.
Can anyone point me in the right direction? Thanks in advance.
change to a left join from your lookup table instead of to your lookup table, or use a right join to your lookup table.
from [dbo].[LOOKUP_WEEK_NUMBER] w
left join ... p
on (p.[Program_Year_ID] = w.[Program_Year_Nbr])
and (p.[Installation_Complete_Date] between w.[Week_Start] and w.[Week_End])

SQL: If there is No match on condition (row in table) return a default value and Rows which match from different tables

I have three tables: Clinic, Stock and StockLog.
I need to get all rows where Stock.stock < 5. I need to also show if an order has been placed and what amount it is; which is found in the table Stocklog.
The issue is that a user can set his stock level in the Stock table without placing an order which would go to Stocklog.
I need a query that can : return the rows in the Stock table and get the related order amounts in the Stocklog table. If no order has been placed in StockLog, then set amount to order amount to zero.
I have tried :
SELECT
Clinic.Name,
Stock.NameOfMedication, Stock.Stock,
StockLog.OrderAmount
FROM
Clinic
JOIN
Stock ON Stock.ClinicID = Clinic.ClinicID
JOIN
StockLog ON StockLog.StockID = Stock.StockID
WHERE
Stock.Stock <= 5
The issue with my query is that I lose rows which are not found in StockLog.
Any help on how to write this.
Thank you.
I am thinking the query should look like this:
SELECT c.Name, s.NameOfMedication, s.Stock,
COALESCE(sl.OrderAmount, 0) as OrderAmount
FROM Stock s LEFT JOIN
Clinic c
ON s.ClinicID = c.ClinicID LEFT JOIN
StockLog sl
ON sl.StockID = s.StockID
WHERE s.Stock <= 5 ;
You want to keep all rows in Stock (subject to the WHERE condition). So think: "make Stock the first table in the FROM and use LEFT JOIN for all the other tables."
If you want to keep all the rows that result from joining Clinic and Stock, then use a LEFT OUTER JOIN with StockLog. I don't know which SQL you're using (SQL Server, MySQL, PostgreSQL, Oracle), so I can't give you a precise example, but searching for "left outer join" in the relevant documentation should work.
See this Stack Overflow post for an explanation of the various kinds of joins.

Perform SQL query and then join

Lets say I have two tables:
ticket with columns [id,date, userid] userid is a foreign key that references user.id
user with columns [id,name]
Owing to really large tables I would like to first filter the tickets table by date
SELECT id FROM ticket WHERE date >= 'some date'
then I would like to do a left join with the user table. Is there a way to do it. I tried the follwoing but it doesnt work.
select ticket.id, user.name from ticket where ticket.date >= '2015-05-18' left join user on ticket.userid=user.id;
Apologies if its a stupid question. I have searched on google but most answers involve subqueries after the join instead of what I want which is to perfrom the query first and then do the join for the items returned
To make things a little more clear, the problem I am facing is that I have large tables and join takes time. I am joining 3 tables and the query takes almost 3 seconds. Whats the best way to reduce time. Instead of joining and then doing the where clause, I figured I should first select a small subset and then join.
Simply put everything in the right order:
select - from - where - group by - having - order by
select ticket.id, user.name
from ticket left join user on ticket.user_id=user.id
where ticket.date >= '2015-05-18'
Or put it in a Derived Table:
select ticket.id, user.name
from
(
select * from ticket
where ticket.date >= '2015-05-18'
) as ticket
left join user on ticket.user_id=user.id