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

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])

Related

Join Two Tables based on a Date Range

I have two tables in my Firebird DB. The first table is called LEDGER and is showing the details of my transaction, including the date of of a transaction (yyyy/mm/dd). The second table is called PERIODS and consists of the following fields:
Period number (INTEGER)
Period start date (yyyy/mm/dd)
Period end date (yyyy/mm/dd)
I want use the date as per the LEDGER table to look up the corresponding period from the PERIODS table and join the two tables based on that. I short, I want to show the period for each line of the ledger table to assist me in preparing consolidated reporting.
Herewith an example of the PERIODS table:
What would be the best approach to do this?
If I was the developer I would have added the period to the ledger table and populate the period on transactional level but unfortunately it is too late for that now.
Any assistance will be greatly appreciated.
You can just use join:
select l.*, p.per
from ledger l left join
periods p
on l.date_of_transaction >= p.start_date and
l.date_of_transaction <= p.end_date
Use below query. Please change the columns names, i have provided the column names as an example.
select P.PER, L.* from LEDGER L
inner join PERIODS P
on (L.date_of_transaction = P.start_date);
select P.PER, L.* from LEDGER L
inner join PERIODS P
on (L.date_of_transaction between P.start_date);

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.

Merge 2 columns from different SQL server table with empty lines

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"?

Compare 2 tables and add missing records to the first, taking into account year/months

I have 2 tables, one with codes and budgets called FACT_QUANTITY_TMP and the other is a tree with all possible codes called C_DS_BD_AP_A.
All codes that exist are in this C_DS_BD_AP_A table, yet not all are in FACT_QUANTITY_TMP. Only those with budget get added by the ERP.
We need all codes to be in this FACT_QUANTITY_TMP table, just with budget to be 0 in that case.
I was trying first to get the missing codes by the following query:
SELECT T2.D_ACTIECODE From
(SELECT distinct
A.FULL_DATE as FULL_DATE, A.DIM03 as DIM03
FROM FACT_QUANTITY_TMP A) T1
RIGHT JOIN
(select distinct B.D_ACTIECODE AS D_ACTIECODE from C_DS_BD_AP_A B) T2
ON
T1.DIM03 = T2.D_ACTIECODE
where T1.DIM03 is null
order by T1.full_date
I get a list of my missing records yet it doesn't take into accounts the FULL_DATE (year and month) of the destination table.
In short, FACT_QUANTITY_TMP needs to have all records added that it's missing grouped by months and year.
Kind of looking for the best approach here, this query would be used in a automatically run stored proc every month when the ERP data gets pulled.
You can generate the missing records by doing a cross join to generate all combinations and then removing those that are already there. For example:
select fd.fulldate, c.D_ACTIECODE
from (select distinct fulldate from fact_quantity_tmp) fd cross join
(select D_ACTIECODE from C_DS_BD_AP_A) c left join
fact_quantity_tmp fqt
on fqt.fulldate = fd.fulldate and fqt.dim03 = c.D_ACTIECODE
where fqt.fulldate is null;
You can put an insert before this to insert these rows into the fact table.

Query to bring back Records from left table if not in right table

Imagine having a Stores table:
ID
StoreNumber
BranchName
Imagine having another "SalesData" table:
ID
Month
Year
StoreNumber
AmountAquired
Stores table is always populated. The SalesData is NOT. It is only populated as and when.
I am struggling to come up with the following query where it will bring me back results where for every store if there is no record for it for the given month and year AND where AmountAquired is null.
At the same time another added complexity (perhaps a separate query) is where to bring back all stores where there is no data in the sales data (with the join on StoreNumber) but if there is data then to only bring back the row for that store that has data and disregard the row which has no data for that store.
I have tried doing a left outer join and right outer join but no go.
SELECT s.* FROM Stores s
LEFT OUTER JOIN SalesData sd ON
sd.StoreNumber = s.StoreNumber
WHERE sd.Year = 2014 AND sd.Month = 11 AND sd.AmountAquired IS NULL.
this brings back only the records where the year and month is 2014 and 11 (not surprising since that is what I put down in the where clause!)
I want it where it brings me back records where there is no data in the salesdata OR where the month and year match the parameters given to it (and not for any other month or any other year unless NULL is in the column values)
It should ALWAYS bring back data (pretty much from the stores table to show all the stores...and any data not found for it in the sales data table (or even if data is there for the given month and year along with for stores which have no data for them)
Hope this makes sense.
You are correct in using a LEFT OUTER JOIN for this type of query. The mistake you made is that when performing a LEFT OUTER JOIN, you need to move filters that are related to the right table into the join on section.
To get only store that are missing sales for Nov 2014:
SELECT s.*
FROM Stores s
LEFT OUTER JOIN SalesData sd ON
sd.StoreNumber = s.StoreNumber
AND sd.Year = 2014 AND sd.Month = 11
WHERE sd.AmountAquired IS NULL --no sales are found
And to get all sales for Nov 2014, including stores that had no sales, you can do this:
SELECT s.*
FROM Stores s
LEFT OUTER JOIN SalesData sd ON
sd.StoreNumber = s.StoreNumber
AND sd.Year = 2014 AND sd.Month = 11
Can you not just switch to an OR for the 2nd case?
(sd.Year = 2014 AND sd.Month = 11) OR sd.AmountAquired IS NULL
In the 1st example you ask for "no record for it for the given month and year AND where AmountAquired is null" - but if there's no record, then AmountAquired will be NULL by necessity.
That query is simply:
SELECT
s.*
FROM
Stores s
LEFT OUTER JOIN SalesData sd ON sd.StoreNumber = s.StoreNumber
WHERE
sd.StoreNumber IS NULL