Join Two Tables based on a Date Range - sql

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

Related

SQL Query Creates Duplicated Results

My task is to produce a report that shows the on time delivery of products to consumers. In essence I have achieved this. However, as you will see only some of the data is accurate.
Here is our test case: we have a sales order number '12312.' This sales order has had 5 partial shipments made (200 pieces each). The result is shown below from our DUE_DTS table.
Due Dates table data
The following code gives me the information I need (excluding due date information) to show the packing details of the 5 shipments:
DECLARE #t AS TABLE (
CUSTNAME char(35),
SONO char(10),
INVDATE date,
PACKLISTNO char(10),
PART_NO char(25),
SOBALANCE numeric(9,2)
)
INSERT INTO #t
SELECT DISTINCT c.CUSTNAME, s.SONO, p.INVDATE, p.PACKLISTNO, i.PART_NO, q.SOBALANCE
FROM [manex].[dbo].[SODETAIL]
INNER JOIN [manex].[dbo].[SOMAIN] s ON s.SONO = SODETAIL.SONO
INNER JOIN [manex].[dbo].[CUSTOMER] c ON c.CUSTNO = s.CUSTNO
INNER JOIN [manex].[dbo].[INVENTOR] i ON i.UNIQ_KEY = SODETAIL.UNIQ_KEY
INNER JOIN [manex].[dbo].[DUE_DTS] d ON d.SONO = s.SONO
INNER JOIN [manex].[dbo].[PLMAIN] p ON p.SONO = s.SONO
INNER JOIN [manex].[dbo].[PLDETAIL] q ON q.PACKLISTNO = p.PACKLISTNO
WHERE s.SONO LIKE '%12312'
SELECT * FROM #t
Here is a screenshot of the results from running this query:
Query Result
Now is when it should be time to join my due dates table (adding in the appropriate column(s) to my table definition and select statement) and make DATEDIFF comparisons to determine if shipments were on time or late. However, once I reference the due dates table, each of the 5 shipments is compared to all 5 dates in the due dates table, resulting in 25 rows. The only linking column DUE_DTS has is the SONO column. I've tried using DISTINCT and variations of the group by clause without success.
I've put enough together myself to figure joining the DUE_DTS table on SONO must be causing this to happen, as there are 5 instances of that value in the table (making it not unique) and a join should be based on a unique column. Is there a workaround for something like this?
You will need to use additional fields to join the records and reduce the results. You may need to link SONO to SODETAIL to DUE_DTS because the dates are tied to the items, not to the SONO.

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.

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

Populating fact table

I've a data warehouse for sales, it has 3 dimensions [product,time,store] and a fact table [sales_fact].
Primary key of 'sales_fact' table is made up of all primary keys of dimensions table, dimension tables are all filled up manually now I want to fill 'sales_fact' table with SUM of prices of products stored in a city for a specific month or 3 month period.
How should I sum up prices from product table which are related to a specific month and add it to fact table?
Considering that sum up prices from product table which are related to a specific month
is a measure, your query can be like below :
SELECT DS.City, DT.[Month], SUM(DP.Price)FROM
SalesFact AS S
LEFT JOIN DimProduct AS DP ON DP.ProductSK=S.ProductSK
LEFT JOIN DimTime AS DT ON DT.DateSK=S.DateSK
LEFT JOIN DimStore AS DS ON DS.StoreSK=S.StoreSK
WHERE [Date condition] --Add your date conditoon
GROUP BY DS.City, DT.[Month]
You can use a view for this measure.

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