I have two tables that need to be joined on the nearest date (nearest before date).
Screenshot of My Requirement
For example: In Table1 Date is 6/19/2018(M/DD/YYYY) then I would like to get the data of nearest before date from the Table2(If table has 07/19/2018, 06/20/2018 and 06/16/2018, I would like to get 06/16/2018 record information).
I have multiple records in table1 and want to get the nearest date record in form from the table2. Please see the image for more info about my requirement. Thank you in advance for your help.
Assuming that you must do it for every customer distinctly (customer column is a key in the example). If you have another key (let's say customer, item_name, item_name column is not shown, add it manually in this case), then change the corresponding predicates (to a[2].customer=x.customer and a[2].item_name=x.item_name in the example). If you don't want to do it for each customer, just remove the predicates a[2].customer=x.customer and.
You can run the statement below AS IS to check.
with
xyz (customer, req_del_date) as (values
('ABC', date('2018-06-19'))
, ('ABC', date('2018-09-04'))
, ('ABC', date('2018-04-24'))
, ('ABC', date('2018-03-17'))
)
, abc (customer, actual_del_date) as (values
('ABC', date('2018-11-20'))
, ('ABC', date('2018-06-12'))
, ('ABC', date('2018-05-09'))
, ('ABC', date('2018-04-27'))
, ('ABC', date('2018-04-14'))
, ('ABC', date('2017-12-31'))
, ('ABC', date('2017-12-30'))
)
select x.customer, x.req_del_date, a.actual_del_date, a.diff_days
from xyz x, table (
select a.customer, a.actual_del_date
, days(x.req_del_date) - days(actual_del_date) diff_days -- just for test
-- other columns from abc if needed
from abc a
where a.customer=x.customer and x.req_del_date>=a.actual_del_date
and (days(x.req_del_date) - days(a.actual_del_date)) =
(
select min(days(x.req_del_date) - days(a2.actual_del_date))
from abc a2
where a2.customer=x.customer and x.req_del_date>=a2.actual_del_date
)
) a;
Related
Currently, the table is ordered in ascending order by row_number. I need help removing duplicates based on 2 conditions.
If there is a stage, that is online then I want to keep that row, doesn't matter which one, there can be multiple.
If there isn't a row with online for that org_id, then I keep row_number = 1 which would be the oldest element.
sales_id
org_id
stage
row_number
ccc_123
ccc
off-line
1
ccc_123
ccc
off-line
2
ccc_123
ccc
online
3
abc_123
abc
off-line
1
abc_123
abc
power-off
2
zzz_123
zzz
power-off
1
so the table should look like this after:
sales_id
org_id
stage
ccc_123
ccc
online
abc_123
abc
off-line
zzz_123
zzz
power-off
Looks like this, stackoverflow not working well with second table for some reason
I would use a combination of a CASE statement to modify the rownumber of records with stage='online' and then use ROW_NUMBER to allow me to filter for the lowest value in a group.
http://sqlfiddle.com/#!17/1421b/5
create table sales_stage (
sales_id varchar,
org_id varchar,
stage varchar,
row_num int);
insert into sales_stage (sales_id, org_id, stage, row_num) values
('ccc_123', 'ccc', 'off-line', 1),
('ccc_123', 'ccc', 'off-line', 2),
('ccc_123', 'ccc', 'online', 3),
('abc_123', 'abc', 'off-line', 1),
('abc_123', 'abc', 'power-off', 2),
('zzz_123', 'zzz', 'power-off', 1);
SELECT
sales_id, org_id, stage
FROM
(
SELECT
sales_id, org_id, stage,
ROW_NUMBER() OVER(PARTITION BY sales_id, org_id ORDER BY row_num) as rn
FROM (
SELECT sales_id, org_id, stage,
CASE WHEN stage='online' THEN -999 ELSE row_num END as row_num
FROM sales_stage
) x
) y
WHERE rn = 1
I have a table with records for sales of products.
For the purpose of sales count a product should only be counted one time.
In this scenario a product is sold and reversed several times and we should only consider it in the month with minimum date and rest all the dates should be marked no.
Eample:
Product Month Sales flag
A Jan-01 Y
B Jan-01 Y
A Feb-01 N
C Feb-01 Y
How can I write a select from the table indicating as above. Any help would be appreciated.
Tried and failed.
The trick here is that ordering by "Jan-01", "Feb-01", etc... is tricky because you need to sort numeric values stored as text. This is one of the uses of a calendar table or data dimension. In my solution below I'm creating an on-the-fly date dimension table with "Month-number" you can sort by...
-- Sample data
DECLARE #table TABLE
(
Product CHAR(1) NOT NULL,
Mo CHAR(6) NOT NULL
)
INSERT #table VALUES
('A', 'Jan-01'),
('B', 'Jan-01'),
('A', 'Feb-01'),
('C', 'Feb-01');
-- Solution
SELECT f.Product, f.Mo, [Sales Flag] = CASE f.rnk WHEN 1 THEN 'Y' ELSE 'N' END
FROM
(
SELECT t.Product, i.Mo, rnk = ROW_NUMBER() OVER (PARTITION BY t.Product ORDER BY i.RN)
FROM #table AS t
JOIN
(
SELECT i.RN, Mo = LEFT(DATENAME(MONTH,DATEADD(MONTH, i.RN-1, '20010101')),3)+'-01'
FROM
(
SELECT RN = ROW_NUMBER() OVER (ORDER BY (SELECT 1))
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS x(x)
) AS i
) AS i ON t.Mo = i.Mo
) AS f;
Returns:
Product Mo Sales Flag
------- ------ ----------
A Jan-01 Y
A Feb-01 N
B Jan-01 Y
C Feb-01 Y
I have this Declare Statement
declare #ReferralLevelData table([Type of Contact] varchar(10));
insert into #ReferralLevelData values ('f2f'),('nf2f'),('Travel'),('f2f'),('nf2f'),('Travel'),('f2f'),('nf2f'),('Travel');
select (row_number() over (order by [Type of Contact]) % 3) +1 as [Referral ID]
,[Type of Contact]
from #ReferralLevelData
order by [Referral ID]
,[Type of Contact];
It does not insert into the table so i feel this is not working as expect, i.e it doesn't modify the table.
If it did work I was hoping to modify the statement to make it update.
At the moment the table just prints this result
1 f2f
1 nf2f
1 Travel
2 f2f
2 nf2f
2 Travel
3 f2f
3 nf2f
3 Travel
EDIT:
I want TO Update the table to enter recurring data in groups of three.
I have a table of data, it is duplicated twice in the same table to make three sets.
Its "ReferenceID" is the primary key, i want to in a way group the 3 same ReferenceID's and inject these three values "f2f" "NF2F" "Travel" into the row called "Type" in any order but ensure that each ReferenceID only has one of those values.
Do you mean the following?
declare #ReferralLevelData table(
[Referral ID] int,
[Type of Contact] varchar(10)
);
insert into #ReferralLevelData([Referral ID],[Type of Contact])
select
(row_number() over (order by [Type of Contact]) % 3) +1 as [Referral ID]
,[Type of Contact]
from
(
values ('f2f'),('nf2f'),('Travel'),('f2f'),('nf2f'),('Travel'),('f2f'),('nf2f'),('Travel')
) v([Type of Contact]);
If it suits you then you also can use the next query to generate data:
select r.[Referral ID],ct.[Type of Contact]
from
(
values ('f2f'),('nf2f'),('Travel')
) ct([Type of Contact])
cross join
(
values (1),(2),(3)
) r([Referral ID]);
The problem is that when I run the query I got an empty table which is wrong base on the data I have, so is my logic wrong or I'm missing something?
Based on the provided tables write a query in HIV SQL to answer question 1
employees ( employee_num , last_name , first_name , status , hire_date , last_date_worked , job_title , job_code , home_branch )
transactions ( branch_num , contract_num , customer_num , invoice_date ,invoice_num , product_num , sales_amount , employee_num , service_date , system_period )
Question 1:
Show the employees who serviced customers before 1/1/2005. Employee
names must be concatenated to produce this format: LastName,
FirstName. For example, “Doe, John”. The result should have two
columns: employee name and service date.
My answer:
SELECT concat(e.first_name, ', ', e.last_name) AS employee_name, t.service_date FROM employees e
FULL OUTER JOIN transactions t
ON e.employee_num = t.employee_num WHERE t.service_date < '1/1/2005';
I have a table punches that looks like this
EMP_ID INpunchDATETIME OUTpunchDATETIME
-----------------------------------------------
1 2017-11-10 11:59 2017-11-10 13:30
1 2017-11-10 9:00 2017-11-10 10:30
I need to create a table #temptable from the previous table that looks like this
Emp_ID InPunch1 InPunch2 OUTpunch1 OUTpunch2
----------------------------------------------------------------------------
1 2017-11-10 9:00 2017-11-10 11:59 2017-11-10 10:30 2017-11-10 13:30
I'm trying to use PIVOT but if that's wrong I can change
DECLARE #temptable Table (
EMP_ID int,
InPunch1 datetime,
InPunch2 datetime,
OutPunch1 datetime,
OutPunch2 datetime);
SELECT
Emp_ID, InPunch1, InPunch2, Outpunch1, Outpunch2
INTO
#temptable
FROM
(SELECT
EMP_ID, INPunchDATETIME, OUTpunchDATETIME
FROM
punches) AS p
PIVOT
(
That's as far as I've got.
Sample Data Setup
create table dbo.punches
(
emp_id int
, INpunchDATETIME datetime
, OUTpunchDATETIME datetime
)
insert into dbo.punches
values (1, '2017-11-10 11:59','2017-11-10 13:30')
, (1, '2017-11-10 9:00','2017-11-10 10:30')
Answer
The punches tables has the in/out punches in two separate column, and the inner most query moves both types of punches into one column to allow all of the data to be pivoted at once. The next query puts them in chronological order, and creates values in punch_ind that will be the eventual column names. Last step is to pivot the data and select the final output.
select post.emp_id
, post.InPunch1
, post.InPunch2
, post.OutPunch1
, post.OutPunch2
from (
--decide which punch is in1/in2/etc.
select sub.emp_id
, sub.punch_type + 'Punch' + cast(row_number() over (partition by sub.emp_id, sub.punch_type order by sub.punch_ts) as varchar(10)) as punch_ind --punch indicator
, sub.punch_ts
from (
--get all of the data in one column to enable pivot
select p.emp_id
, 'In' as punch_type
, p.INpunchDATETIME as punch_ts
from dbo.punches as p
union all
select p.emp_id
, 'Out' as punch_type
, p.OUTpunchDATETIME as punch_ts
from dbo.punches as p
) as sub
) as pre --before the pivot
pivot (max(pre.punch_ts) for pre.punch_ind in ([InPunch1], [InPunch2], [OutPunch1], [OutPunch2])) as post --after the pivot
Just take this final output and insert the records into the temp table/table variable of your choice.