I have a table like shown below:
name field value
---- ----- -----
a p 1
a q 2
b p 5
c q 7
d p 4
e p 3
e q 2
. . .
. . .
. . .
Expected Output :
name p q . . . . .
---- --- --- --- --- --- --- ---
a 1 2
b 5
c 7
d 4
e 3 2
. . .
. . .
. . .
How to the field elements in column like shown above...
I think you can use a query like this:
select name,
sum(case when field = "p" then value else 0 end) p,
sum(case when field = "q" then value else 0 end) q,
...
from yourTable
group by name;
Related
I have a table that looks like this
id
name
count
1
Nishu
4
2
Shivam
2
3
Himanshu
1
I want to get the Output like this:-
id
name
count
1
Nishu
4
1
Nishu
4
1
Nishu
4
1
Nishu
4
2
Shivam
2
2
Shivam
2
3
Himanshu
1
3
Himanshu
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
You can use a cross join against generate_series()
select t.*
from the_table t
cross join generate_series(1, t.count) as g
order by t.id;
Online example
Using RECURSIVE CTE you can do:
WITH RECURSIVE cte as (
SELECT 1 as x,m.* FROM mytable m
union all
SELECT x+1,m.*
FROM cte,mytable m
WHERE x<m.count)
SELECT DISTINCT *
FROM cte
ORDER BY count DESC;
see: DBFIDDLE
more info:
WITH Queries (Common Table Expressions)
Learn PostgreSQL Recursive Query By Example
I'm using ROW_NUMBER() and PARTITION BY to create a table that looks like this:
VALUE ID ROWNUM
A 4525 1
B 4526 1
C 4527 1
D 4530 1
E 4530 2
F 4530 3
G 4531 1
H 4531 2
I want to get rid of the partitions that consist of only one value. A, B, and C will be gone, but D through H will stay because they're in partitions that contain more than one value. In other words, what can I do to my query to make the results look like this:
VALUE ID ROWNUM
D 4530 1
E 4530 2
F 4530 3
G 4531 1
H 4531 2
I can't filter by ROWNUM > 1 because I want to keep some of the columns where ROWNUM = 1, but figuring out how to keep only some of those columns is stumping me.
However you are calculating rownum, also calculate count(*):
select value, id, rownum
from (select t.*,
row_number() over (partition by . . . order by . . . ) as rownum,
count(*) over (partition by . . . ) as cnt
from t
) t
where cnt > 1;
The partition by should be the same for the two window functions.
I have a table as shown below. How do I write the SQL code if I want to count the number of times the row (e.g. X = A, Y = Burger) appear and return as Z? Thanks
Select * X, Y
from DataBase
Results :
X Y Z(to be determined..)
--------------------
A Burger 2
A Burger 2
A Fries 1
B Burger 2
B Pie 1
B Burger 2
C Pie 2
C Pie 2
C Burger 1
. . .
. . .
. . .
You can do:
select X,Y,count(*) from Table group by X,Y
You are looking for a window function:
select t.*, count(*) over (partition by x, y) as z
from DataBase t;
I have a data set containing an unbalanced panel of observations, where I want to forward and backward fill missing and/or "wrong" observations of ticker with the latest non-missing string.
id time ticker_have ticker_want
------------------------------
1 1 ABCDE YYYYY
1 2 . YYYYY
1 3 . YYYYY
1 4 YYYYY YYYYY
1 5 . YYYYY
------------------------------
2 4 . ZZZZZ
2 5 ZZZZZ ZZZZZ
2 6 . ZZZZZ
------------------------------
3 1 . .
------------------------------
4 2 OOOOO OOOOO
4 3 OOOOO OOOOO
4 4 OOOOO OOOOO
Basically, if the observation already has a ticker, but this ticker is not the same as the latest non-empty ticker, we replace this ticker using the latest ticker.
So far, I have managed to fill missing observations forward using this code
proc sql;
create table have as select * from old_have order by id, time desc;
quit;
data want;
drop temp;
set have;
by id;
/* RETAIN the new variable*/
retain temp; length temp $ 5;
/* Reset TEMP when the BY-Group changes */
if first.id then temp=' ';
/* Assign TEMP when X is non-missing */
if ticker ne ' ' then temp=ticker;
/* When X is missing, assign the retained value of TEMP into X */
else if ticker=' ' then ticker=temp;
run;
Now I am stuck figuring out the cases where I can't access the non-missing value using last.ticker or first.ticker ...
How would one do this using DATA or PROC SQL or any other SAS commands?
You can do this several ways, but proc sql with some nested sub-queries is one solution.
(Read it from inside out, #1 then 2 then 3. You could build each subquery into a dataset first if it helps)
proc sql ;
create table want as
/* #3 - match last ticker on id */
select a.id, a.time, a.ticker_have, b.ticker_want
from have a
left join
/* #2 - id and last ticker */
(select x.id, x.ticker_have as ticker_want
from have x
inner join
/* #1 - max time with a ticker per id */
(select id, max(time) as mt
from have
where not missing(ticker_have)
group by id) as y on x.id = y.id and x.time = y.mt) as b on a.id = b.id
;
quit ;
Consider using a data step to retrieve the last ticker by time for each id, then joining it to main table. Also, use a CASE statement to conditionally assign new ticker if missing or not.
data LastTicker;
set Tickers (where=(ticker_have ~=""));
by id;
first = first.id;
last = last.id;
if last = 1;
run;
proc sql;
create table Tickers_Want as
select t.id, t.time, t.ticker_have,
case when t.ticker_have = ""
then l.ticker_have
else t.ticker_have
end as tickerwant
from Tickers t
left join LastTicker l
on t.id = l.id
order by t.id, t.time;
quit;
Data
data Tickers;
length ticker_have $ 5;
input id time ticker_have $;
datalines;
1 1 ABCDE
1 2 .
1 3 .
1 4 YYYYY
1 5 .
2 4 .
2 5 ZZZZZ
2 6 .
3 1 .
4 2 OOOOO
4 3 OOOOO
4 4 OOOOO
;
Output
Obs id time ticker_have tickerwant
1 1 1 ABCDE ABCDE
2 1 2 YYYYY
3 1 3 YYYYY
4 1 4 YYYYY YYYYY
5 1 5 YYYYY
6 2 4 ZZZZZ
7 2 5 ZZZZZ ZZZZZ
8 2 6 ZZZZZ
9 3 1
10 4 2 OOOOO OOOOO
11 4 3 OOOOO OOOOO
12 4 4 OOOOO OOOOO
I have Two Tables Let Say "Table1" and "Table2"
Table1
ID AccountId BranchId otherColumn
----------- ---------- ---------- -----------
1 15 58 data
2 22 62 data
3 31 89 data
4 49 45 data
. . . .
. . . .
. . . .
. . . .
. . . .
Table2
ID fromAccount toAccount ExcludeAccount IncludeAccount FromBranch ToBranch IncludeBranch ExcludeBranch
----------- ---------- ---------- ----------- ---------- --------- ------------ -------------- ------------
1 1 90 89,34,3 101 30 100 205,207,250 35,40
1 5 67 90 22 50 70,90 20
2 7 4 3 5 200
2 1 5 7 10 16 9
3 5 89 6,7 200 55 243 34 35,200,201,234
Now I want to select All data from Table1 using expression from Table1
I have Function that converts the comma separated text to table
select data from dbo.split('23,45,2', ',')
this will return
data
------
23
45
2
My Desired Output for row 1 is
ID AccountId BranchId otherColumn
----------- ---------- ---------- -----------
. 1 . data
. 2 . data
. 4 . data
. 5 . data
. 6 . data
. 7 . data
. 8 . data
. . . .
. . . .
. 33 . .
. 35 . .
. . . .
. 88 . .
. 90 . .
. 101 . .
. . 30 .
. . 31 .
. . . .
. . 34 .
. . 36 .
. . . .
I have created query to get data with relation of these two table But it always returns no row
here is my query
select * from Table1
inner join Table2 on Table1.AccountId between Table2.fromAccount and Table2.toAccount
and Table1.AccountId not in (select data from dbo.split(Table2.ExcludeAccount, ','))
and Table1.AccountId in (select data from dbo.split(Table2.IncludeAccount, ','))
and Table1.BranchId between Table2.FromBranch and Table2.ToBranch
and Table1.BranchId not in (select data from dbo.split(Table2.ExcludeAccount, ','))
and Table1.BranchId in (select data from dbo.split(Table2.IncludeAccount, ','))
my question is, why it always returns no data is any thing wrong in my query or i am doing it in wrong way
not in is generally not what you want with a subquery. If any of the values returned by the subquery are NULL, then nothing at all passes the filter. Instead, get used to using not exists.
For instance, instead of:
not in (select data from dbo.split(Table2.ExcludeAccount, ','))
Use:
not exists (select 1
from dbo.split(Table2.ExcludeAccount, ',') s(p)
where Table1.BranchId = s.p
)
You may also have a problem with data types, but SQL Server should be converting them correctly.