I have two tables I have to retrieve data from both table with out duplication of rows .
there is table (a)
BILL_DATE BILL_AMOUNT
----------
20160208 94
20160208 140
20160208 30
20160208 25
20160208 14
20160208 6
20160208 35
20160208 20
20160208 35
=======================
second table is (b)
and i want to result like
You could use a full outer join on the date in order to take the relevant row from whichever table has it:
SELECT COALESCE(bill_date, reach_date) AS [date],
bill_date, bill_amount,
reach_date AS [recharge_date], reach_amount AS [recharge_amount]
FROM a
FULL OUTER JOIN b on a.bill_date = b.reach_date
Question is not clear but if you want 13 rows
select bill_date as "DATE", bill_date, bill_amount, null as "recharge_date" , null as "recharge_amount"
from a
union all
select rech_date , null , null , rech_date , rech_amount
from b;
Not clear how you are going to get 100, 200, 300, 400 for rech_amount
Try this:
SELECT ISNULL(X.BILL_DATE,X.RECHARGE_DATE) AS DATE,X.*
FROM (
SELECT BILL_DATE,BILL_AMOUNT as BILL_AMT,null as RECHARGE_DATE,null as RECHARGE_AMT
FROM Tablea
UNION ALL
SELECT null as BILL_DATE,null as BILL_AMT,RECH_DATE as RECHARGE_DATE,RECH_AMOUNT as RECHARGE_AMT
FROM Tableb
) X
Related
I have a Table that is joined from other tables. I want to update a null value in this Table by a specific number series. Below is the illustration:
The code for the Table which is called List_Codes
SELECT mlk.MLK_CODE
FROM zpt
LEFT OUTER JOIN mes ON mes.ZPT_ID = zpt.ZPT_ID
LEFT OUTER JOIN zmlk ON zpt.ZPT_ID = zmlk.ZPT_ID
LEFT OUTER JOIN mlk ON zmlk.MLK_ID = mlk.MLK_ID
WHERE zpt.zpt_id IS NOT NULL
and zpt.zpt_meteringcode = '123456'
ORDER BY mes.MES_STATUS DESC
Now I want to update this specific row's mlk.MLK_CODE from null to '789'. I have located this row based on the zpt.zpt_meteringcode. Any suggestions plz?
The tables look like this, and the List_Code Table is the result of the above code
Mlk Table
Mlk_id Mlk_code
1 123
2 456
Zpt Table
Zpt_id Zpt_meteringcode
10 123456
20 987654
30 654321
40 147852
Zmlk Table
Zpt_id Mlk_id
20 1
30 2
List_Code Table
Zpt_id Zpt_meteringcode Mlk_id Mlk_code
10 123456
20 987654 1 123
30 654321 2 456
40 147852
I think you need two inserts and one update statements like this.
INSERT INTO mlk (mlk_code)
VALUES ( '789' ); -- Primary key is generated
.....
INSERT INTO zmlk (zpt_id,
mlk_id)
SELECT (SELECT zpt_id
FROM zpt
WHERE zpt_meteringcode = '123456'),
(SELECT mlk_id
FROM mlk
WHERE mlk_code = '789')
FROM dual;
....
UPDATE list_code
SET ( mlk_id, mlk_code ) = (SELECT mlk_id,
mlk_code
FROM mlk
WHERE mlk_code = '789')
WHERE zpt_meteringcode = '123456';
The table I have now looks something like this. Each row has a time value (on which the table is sorted in ascending order), and two values which can be replicated across rows:
Key TimeCall R_ID S_ID
-------------------------------------------
1 100 40 A
2 101 50 B
3 102 40 C
4 103 50 D
5 104 60 A
6 105 40 B
I would like to return something like this, wherein for each row, a JOIN is applied such that the S_ID and Time_Call of the next row that shares that row's R_ID is displayed (or is NULL if that row is the last instance of a given R_ID). Example:
Key TimeCall R_ID S_ID NextTimeCall NextS_ID
----------------------------------------------------------------------
1 100 40 A 102 C
2 101 50 B 103 D
3 102 40 C 105 B
4 103 50 D NULL NULL
5 104 60 A NULL NULL
6 105 40 B NULL NULL
Any advice on how to do this would be much appreciated. Right now I'm joining the table on itself and staggering the key on which I'm joining, but I know this won't work for the instance that I've outlined above:
SELECT TOP 10 Table.*, Table2.TimeCall AS NextTimeCall, Table2.S_ID AS NextS_ID
FROM tempdb..#Table AS Table
INNER JOIN tempdb..#Table AS Table2
ON Table.TimeCall + 1 = Table2.TimeCall
So if anyone could show me how to do this such that it can call rows that aren't just consecutive, much obliged!
Use LEAD() function:
SELECT *
, LEAD(TimeCall) OVER (PARTITiON BY R_ID ORDER BY [Key]) AS NextTimeCall
, LEAD(S_ID) OVER (PARTITiON BY R_ID ORDER BY [Key]) AS NextS_ID
FROM Table2
ORDER BY [Key]
SQLFiddle DEMO
This is only test example I had close by ... but i think it could help you out, just adapt it to your case, it uses Lag and Lead ... and it's for SQL Server
if object_id('tempdb..#Test') IS NOT NULL drop table #Test
create table #Test (id int, value int)
insert into #Test (id, value)
values
(1, 1),
(1, 2),
(1, 3)
select id,
value,
lag(value, 1, 0) over (order by id) as [PreviusValue],
lead(Value, 1, 0) over (order by id) as [NextValue]
from #Test
Results are
id value PreviusValue NextValue
1 1 0 2
1 2 1 3
1 3 2 0
Use an OUTER APPLY to select the top 1 value that has the same R_ID as the first Query and has a higher Key field
Just change the TableName to the actual name of your table in both parts of the query
SELECT a.*, b.TimeCall as NextTimeCall, b.S_ID as NextS_ID FROM
(
SELECT * FROM TableName as a
) as a
OUTER APPLY
(
SELECT TOP 1 FROM TableName as b
WHERE a.R_ID = b.R_ID
AND a.Key > B.Key
ORDER BY Key ASC
) as b
Hope this helps! :)
For older versions, here is one trick using Outer Apply
SELECT a.*,
nexttimecall,
nexts_id
FROM table1 a
OUTER apply (SELECT TOP 1 timecall,s_id
FROM table1 b
WHERE a.r_id = b.r_id
AND a.[key] < b.[key]
ORDER BY [key] ASC) oa (nexttimecall, nexts_id)
LIVE DEMO
Note : It is better to avoid reserved keywords(Key) as column/table names.
So I have 2 tables, team A and team B, with their score. I want the rank of the score of every member of team A within team B using SQL or vertica, as shown below
Team A Table
user score
-------------
asa 100
bre 200
cqw 50
duy 50
Team B Table
user score
------------
gfh 20
ewr 80
kil 70
cvb 90
Output:
Team A Table
user score rank in team B
------------------------------
asa 100 1
bre 200 1
cqw 50 4
duy 50 4
Try this - and this only works in Vertica.
INTERPOLATE PREVIOUS VALUE is an outer-join predicate specific to Vertica that joins two tables on non-equal columns, using the 'last known' value in the outer-joined table to make a match succeed.
WITH
-- input, don't use in query itself
table_a (the_user,score) AS (
SELECT 'asa',100
UNION ALL SELECT 'bre',200
UNION ALL SELECT 'cqw',50
UNION ALL SELECT 'duy',50
)
,
table_b(the_user,score) AS (
SELECT 'gfh',20
UNION ALL SELECT 'ewr',80
UNION ALL SELECT 'kil',70
UNION ALL SELECT 'cvb',90
)
-- end of input - start WITH clause here
,
ranked_b AS (
SELECT
RANK() OVER(ORDER BY score DESC) AS the_rank
, *
FROM table_b
)
SELECT
a.the_user AS a_user
, a.score AS a_score
, b.the_rank AS rank_in_team_b
FROM table_a a
LEFT JOIN ranked_b b
ON a.score INTERPOLATE PREVIOUS VALUE b.score
ORDER BY 1
;
a_user|a_score|rank_in_team_b
asa | 100| 1
bre | 200| 1
cqw | 50| 4
duy | 50| 4
Simple correlated query should do:
select
a.*,
(select count(*) + 1 from table_b b where b.score > a.score) rank_in_b
from table_a a;
All you need to do is count the number of people with more score than current user in the table b and add 1 to it to get the rank.
I've got a resultset that looks something like:
[DateField ][Hour][Value]
2014-10-01 1 200
2014-10-01 2 600
I need to add a couple of additional columns from another table like:
[DateField ][Hour][Value][T2Value1][T2Value2]
2014-10-01 1 200 Off 5
2014-10-01 2 600 Off 7
I need the T2Value1 and T2Value2 from Table 2 below if the Value field from Table 1 falls between the RangeValue1 and RangeValue2 of Table 2.
[Id][T2Value1][T2Value2][RangeValue1][RangeValue2]
1 Off 5 1 500
2 Off 7 501 1000
I've started to query
select datefield, hour, value, t2value1, t2value2 from
(
-- inner query that returns datefield, hour, value
) Table1, Table2
but don't know where to take it from here. Would appreciate any help, thanks!
See this simple example:
declare #Values as table
(
Name varchar(10) not null
,Value int not null
)
declare #Ranges as table
(
Grade char(1) not null
,v0 int not null
,v1 int not null
)
insert into #Values
values
('Albert', 33)
,('Bob', 133)
,('Carl', 233)
insert into #Ranges
values
('A',0,100)
,('B',100,200)
,('C',200,300)
select * from #Values v
join #Ranges r on r.v0 <= v.Value and v.Value < r.v1
As you can see it's ok to put some more complex condition on the join clause, in this case a range condition
it results in:
Name Value Grade v0 v1
---------- ----------- ----- ----------- -----------
Albert 33 A 0 100
Bob 133 B 100 200
Carl 233 C 200 300
A simple join should get you what you need. The on condition is a little more complicated than normal, but not much.
select t1.DateField, t1.Hour, t2.t2value1, t2.t2value2
from table1 t1
inner join table2 t2 on t2.RangeValue1 <= t1.Value and t1.Value <= t2.RangeValue2
I have two tables,
Table1:
Key, Value
----------
1 10
2 20
3 30
Table2:
Key, Value
----------
3 30
4 40
5 50
How can merge them and get the following using SQL?
Desired output:
Key, Value
----------
1 10
2 20
3 60
4 40
5 50
In Python terminology, I guess it is called summing up two dictionaries.
PS: I am using Oracle 12c.
Use Union all to combine two select queries and sum the value with group by key column
select key,sum(value) value
from
(
select Key, Value from table1
union all
select Key, Value from table2
) a
group by key
or use Full outer Join
SELECT COALESCE(a.Key, b.key),
COALESCE(a.Value, 0) + COALESCE(b.value, 0)
FROM table1 a
FULL OUTER JOIN Table2 b
ON a.Key = b.Key
For more efficient in terms of speed, as much as possible avoid using UNION/UNION ALL. Try my answer below:
SELECT
NVL(A.Key,B.Key)[Key],
(NVL(A.Value,0) + NVL(B.Value,0))[Value]
FROM Table1 A
FULL JOIN Table2 B ON A.Key=B.Key