how do I join on the same column multiple times, one of the tables is a configuration table with values and other is the data table.
T1:
ID Seq Code1 Code2 Code3
1 001 101 203 305
1 002 107
2 001 103
3 005 213
4 009 320
5 001 101 314
T2 (Config table):
Value Description
101 Strawberry
103 Raspberry
107 Blueberry
111 Banana
203 Cashews
213 Almonds
305 Bellpepper
320 Tomatoes
314 Potatoes
I need to display the code and its relevant description for each ID.
Expected Output:
ID Code1 Description Code2 Description Code3 Description
1 101 Strawberry 203 Cashews 305 Bellpepper
1 107 Blueberry
2 103 Raspberry
3 213 Almonds
4 320 Tomatoes
5 101 Strawberry 314 Potatoes
This is what I have tried so far, however, it is not giving me the desired output:
select distinct ID,code1, T2.description,
code2, T2.description, code3, T2.description
from T1,T2
where (T1.Code1=T2.Value OR T1.Code2=T2.Value or T1.Code3=T2.Value)
How can I achieve this? Sorry if my question is confusing, I can provide more details if needed.
That's multiple outer join with the t2 table:
select a.id, a.seq,
a.code1, d1.description,
a.code2, d2.description,
a.code3, d3.description
from t1 a left join t2 d1 on a.code1 = d1.value
left join t2 d2 on a.code2 = d2.value
left join t2 d3 on a.code3 = d3.value
order by a.id, a.seq;
ID SEQ CODE1 DESCRIPTIO CODE2 DESCRIPTIO CODE3 DESCRIPTIO
----- --- ---------- ---------- ---------- ---------- ---------- ----------
1 001 101 Strawberry 203 Cashews 305 Bellpepper
1 002 107 Blueberry
2 001 103 Raspberry
3 005 213 Almonds
4 009 320 Tomatoes
5 001 101 Strawberry 314 Potatoes
I have table and have a data as follows
Ac1 ac2 name ind
123 223 john y
123 000 john y
123 001 john N
123 002 roy N
223 000 roy N
223 001 roy Y
223 002 james y
234 001 james y
234 000 james y
I have this table I want to show ac2 is other than 000 any other value i need to show the ind1 new column as the ind of 000 value
Ac1 ac2 name ind ind1
123 223 john y Y
123 000 john y Y
123 001 john N Y
123 002 roy N N
223 000 roy N N
223 001 roy Y N
223 002 james y Y
234 001 james y Y
234 000 james y Y
My table always has account with 000 and now if i want to view it by name then I am not getting expected result
select ac1, ac2, ind,case when ac2 = 0 then ind end as ind1 from table;
select a.ac1, a.ac2, a.name, a.ind, b.ind ind1
from table a join (select distinct name, ind from table where ac2='000')b on a.name=b.name
I have two tables: balance and calendar.
Balance :
Account Date Balance
1111 01/01/2014 100
1111 02/01/2014 156
1111 03/01/2014 300
1111 04/01/2014 300
1111 07/01/2014 468
1112 02/01/2014 300
1112 03/01/2014 300
1112 06/01/2014 300
1112 07/01/2014 350
1112 08/01/2014 400
1112 09/01/2014 450
1113 01/01/2014 30
1113 02/01/2014 40
1113 03/01/2014 45
1113 06/01/2014 45
1113 07/01/2014 60
1113 08/01/2014 50
1113 09/01/2014 20
1113 10/01/2014 10
Calendar
date business_day_ind
01/01/2014 N
02/01/2014 Y
03/01/2014 Y
04/01/2014 N
05/01/2014 N
06/01/2014 Y
07/01/2014 Y
08/01/2014 Y
09/01/2014 Y
10/01/2014 Y
I need to do the following:
I need to fill in the missing days for all the accounts up to the maximum day for which it has value. Say for account 1111, it has value only till 07/01/2014, so the dates need to be filled only till that. But when I join with the calendar table (plain left join), I am not able restrict the maximum day to the day available for an account.
1111 01/01/2014 100 N
1111 02/01/2014 156 Y
1111 03/01/2014 300 Y
1111 04/01/2014 300 Y
1111 05/01/2014 N
1111 06/01/2014 N
1111 07/01/2014 468 Y
1111 08/01/2014 Y
1111 09/01/2014 Y
1111 10/01/2014 Y
1112 01/01/2014 N
1112 02/01/2014 300 Y
1112 03/01/2014 300 Y
1112 04/01/2014 N
1112 05/01/2014 N
1112 06/01/2014 300 Y
1112 07/01/2014 350 Y
1112 08/01/2014 400 Y
1112 09/01/2014 450 Y
1112 10/01/2014 Y
I need an efficient way (preferably not involving multiple steps) to restrict the dates up to an account's maximum balance available date (07/01/2014 in case of 1111,09/01/2014 in case 1112)
Desired output:
1111 01/01/2014 100 N
1111 02/01/2014 156 Y
1111 03/01/2014 300 Y
1111 04/01/2014 300 Y
1111 05/01/2014 N
1111 06/01/2014 N
1111 07/01/2014 468 Y
1112 01/01/2014 N
1112 02/01/2014 300 Y
1112 03/01/2014 300 Y
1112 04/01/2014 N
1112 05/01/2014 N
1112 06/01/2014 300 Y
1112 07/01/2014 350 Y
1112 08/01/2014 400 Y
1112 09/01/2014 450 Y
After filling the missing days, I am planning to impute the balance of previous business day to the missing days. I am planning to get previous business day for every date and do an update to missing rows by joining the original balance table with acct and previous business day as key.
Thanks.
I am Greenplum database.
A possible way would be put a second select in a subquery. For instance:
select ... from calendar a left outer join balance b on a.date = b.date
where a.date <= (select max(date) from balance c where b.Account = c.Account )
I suppose that you have third table, accounts:
select
accounts.account,
calendar.date,
balance.balance,
calendar.business_day_ind
from
accounts cross join lateral (
select *
from calendar
where calendar.date <= (
select max(date)
from balance
where balance.account = accounts.account)) as calendar left join
balance on (balance.account = accounts.account and balance.date = calendar.date)
order by
accounts.account, calendar.date;
About lateral joins
That was a fun challenge!
CREATE TABLE balance
(account int, balance_date timestamp, balance int)
DISTRIBUTED BY (account, balance_date);
INSERT INTO balance
values (1111,'01/01/2014', 100),
(1111, '02/01/2014', 156),
(1111, '03/01/2014', 300),
(1111, '04/01/2014', 300),
(1111, '07/01/2014', 468),
(1112, '02/01/2014', 300),
(1112, '03/01/2014', 300),
(1112, '06/01/2014', 300),
(1112, '07/01/2014', 350),
(1112, '08/01/2014', 400),
(1112, '09/01/2014', 450),
(1113, '01/01/2014', 30),
(1113, '02/01/2014', 40),
(1113, '03/01/2014', 45),
(1113, '06/01/2014', 45),
(1113, '07/01/2014', 60),
(1113, '08/01/2014', 50),
(1113, '09/01/2014', 20),
(1113, '10/01/2014', 10);
CREATE TABLE calendar
(calendar_date timestamp, business_day_ind boolean)
DISTRIBUTED BY (calendar_date);
INSERT INTO calendar
values ('01/01/2014', false),
('02/01/2014', true),
('03/01/2014', true),
('04/01/2014', false),
('05/01/2014', false),
('06/01/2014', true),
('07/01/2014', true),
('08/01/2014', true),
('09/01/2014', true),
('10/01/2014', true);
analyze balance;
analyze calendar;
And now the query.
select d.account, d.my_date, b.balance, c.business_day_ind
from (
select account, start_date + interval '1 month' * (generate_series(0, duration)) AS my_date
from (
select account, start_date, (date_part('year', duration) * 12 + date_part('month', duration))::int as duration
from (
select start_date, age(end_date, start_date) as duration, account
from (
select account, min(balance_date) as start_date, max(balance_date) as end_date
from balance
group by account
) as sub1
) as sub2
) sub3
) as d
left outer join balance b on d.account = b.account and d.my_date = b.balance_date
join calendar c on c.calendar_date = d.my_date
order by d.account, d.my_date;
Results:
account | my_date | balance | business_day_ind
---------+---------------------+---------+------------------
1111 | 2014-01-01 00:00:00 | 100 | f
1111 | 2014-02-01 00:00:00 | 156 | t
1111 | 2014-03-01 00:00:00 | 300 | t
1111 | 2014-04-01 00:00:00 | 300 | f
1111 | 2014-05-01 00:00:00 | | f
1111 | 2014-06-01 00:00:00 | | t
1111 | 2014-07-01 00:00:00 | 468 | t
1112 | 2014-02-01 00:00:00 | 300 | t
1112 | 2014-03-01 00:00:00 | 300 | t
1112 | 2014-04-01 00:00:00 | | f
1112 | 2014-05-01 00:00:00 | | f
1112 | 2014-06-01 00:00:00 | 300 | t
1112 | 2014-07-01 00:00:00 | 350 | t
1112 | 2014-08-01 00:00:00 | 400 | t
1112 | 2014-09-01 00:00:00 | 450 | t
1113 | 2014-01-01 00:00:00 | 30 | f
1113 | 2014-02-01 00:00:00 | 40 | t
1113 | 2014-03-01 00:00:00 | 45 | t
1113 | 2014-04-01 00:00:00 | | f
1113 | 2014-05-01 00:00:00 | | f
1113 | 2014-06-01 00:00:00 | 45 | t
1113 | 2014-07-01 00:00:00 | 60 | t
1113 | 2014-08-01 00:00:00 | 50 | t
1113 | 2014-09-01 00:00:00 | 20 | t
1113 | 2014-10-01 00:00:00 | 10 | t
(25 rows)
I had to get the min and max dates for each account and then use generate_series to generate the months between the two dates. It would have been a bit cleaner query if you wanted a record for each day but I had to use another subquery to get the results at a monthly level.
I'm trying to eliminate duplicate rows from an Access dataset made up of two tables table1 and table2. I want to retrieve the distinct values from one column and fields from two tables, but also retrieve the values of other columns of duplicates and unique values.
Sample data (not actual data):
Table 1:
ID BOM_PART_NAME PART FIND NO POS LCN POS_CT
1 E 0001 1 P0 1
2 A 0002 1 P1 1
3 C 0003 1 P2 1
4 D 0004 1 P3 1
5 F 0005 1 P4 1
Table 2:
ID PART-ATA-NO PART-SN PART-NAME
1 001 A
2 002 B
3 003 C
4 004 1100 D
5 005 1101 E
Table 2:
ID PART-ATA-NO PART-SN PART-NAME
1 001 A
2 002 B
3 003 C
4 004 1100 D
5 005 1101 E
What I'm getting (just showing major columns in result set to keep brief):
ID ... PART FIND NO POS PART-ATA-NO PART-SN
1 001 1 001 1369
2 002 1 002 1444
3 003 1 003 1100
3 003 1 003 1101
3 003 1 003 1102
4 003 2 003 1101
4 003 2 003 1102
5 004 1 004 1101
5 004 1 004 1102
Desired Result:
ID PART FIND NO POS PART-ATA-NO PART-SN
1 001 1 001 1369
2 002 1 002 1444
3 003 1 003 1100
4 003 2 003 1101
5 003 3 003 1102
6 003 4 003 1103
7 003 5 003 1104
8 004 1 004 1105
9 004 2 004 1106
ID PART FIND NO POS PART-ATA-NO PART-SN
1 001 1 001 1369
2 002 1 002 1444
3 003 1 003 1100
3 003 1 003 1101
3 003 1 003 1102
4 003 2 003 1101
4 003 2 003 1102
5 004 1 004 1101
5 004 1 004 1102
Desired Result:
ID PART FIND NO POS PART-ATA-NO PART-SN
1 001 1 001 1369
2 002 1 002 1444
3 003 1 003 1100
4 003 2 003 1101
5 003 3 003 1102
6 003 4 003 1103
7 003 5 003 1104
8 004 1 004 1105
9 004 2 004 1106
With matching PART FIND NO's (and PART-ATA-NO's), POS should be incremented by 1. The SN's should all be unique.
The query I used to join the two tables:
SELECT Table1.*, Table2.[PART-ATA-NO], Table2.[PART-SN]
FROM Table1 INNER JOIN Table2 ON Table1.[PART FIND NO] = Table2.[PART-ATA-NO];
The field I want unique values from is [PART-SN] from table2. I want to select all other fields from table1 and [PART-SN] from table 2, of which all rows should be returned for all distinct rows of [PART-SN]. [PART FIND NO] and [PART-ATA-NO] have equivalent values. Is there a way to join the two tables to get this result?
I have a dimensions table
#dimensions
Dateid Rep Mkt Prodgroup
201111 002 S 001
201111 002 R 001
201111 002 S 002
201111 002 R 002
201111 002 S 003
201111 002 R 003
201111 002 S 004
201111 002 R 004
...
I want to join it with this table to include the percentage.
#percentageincrease
Prodgroup Mkt Percent
ALL S 1.05
ALL R 1.06
002 S 1.07
002 R 1.08
003 S 1.09
003 R 1.10
I want to join them on Mkt and Prodgroup where #dimensions.Prodgroup IN #percentageincrease.Prodgroup and if not in then to join on the ALL. So the output table would be
Dateid Rep Mkt Prodgroup Percent
201111 002 S 001 1.05 // joined on ALL
201111 002 R 001 1.06 // joined on ALL
201111 002 S 002 1.07 // joined on 002
201111 002 R 002 1.08 // joined on 002
201111 002 S 003 1.09 // joined on 003
201111 002 R 003 1.10 // joined on 003
201111 002 S 004 1.05 // joined on ALL
201111 002 R 004 1.06 // joined on ALL
...
As my join condition I have tried
on case p.Prodgroup
when N'ALL'
then d.prodgrpid
else p.Prodgrpid = d.prodgrpid
AND p.Mkt = d.Mkt
but it gave me
Dateid Rep Mkt Prodgroup Percent
201111 002 S 001 1.05
201111 002 R 001 1.06
201111 002 S 002 1.07
201111 002 R 002 1.08
201111 002 S 002 1.05 //Joined on ALL
201111 002 R 002 1.06 //Joined on ALL
201111 002 S 003 1.09
201111 002 R 003 1.10
201111 002 S 003 1.05 //Joined on ALL
201111 002 R 003 1.06 //Joined on ALL
201111 002 S 004 1.05
201111 002 R 004 1.06
...
where the tuples which were in the #percentageincrease table were also joined on the ALL condition.
This is being run on SQL Server 2008 as a stored procedure as part of a larger query.
Assuming the table structures
declare #dimensions table
(Dateid varchar(10), Rep varchar(10), Mkt varchar(10),Prodgroup varchar(10))
declare #percentageincrease table
(Prodgroup varchar(10), Mkt varchar(10), [Percent] decimal(9,5))
then
select
d.*,
isnull(pinc.[Percent], pincall.[Percent])
from #dimensions d
left join #percentageincrease pinc
on d.Mkt = pinc.Mkt
and d.Prodgroup = pinc.Prodgroup
left join #percentageincrease pincall
on d.Mkt = pincall.Mkt
and pincall.Prodgroup ='all'
try this:
select * from
(
select d.*,p.[Percent] from
dimensions d inner join percentageincrease p
on d.Mkt = p.Mkt and d.Prodgroup = p.Prodgroup
union
select d.*,p.[Percent] from
dimensions d join percentageincrease p
on d.Mkt = p.Mkt and d.Prodgroup not in
(select distinct d.Prodgroup from dimensions d inner join percentageincrease p
on d.Mkt = p.Mkt and d.Prodgroup = p.Prodgroup)
where p.Prodgroup='ALL'
) a
order by a.Prodgroup