How to Sum Groups and provide totals in separate columns? - tsql

I have beek looking at this problem for a while and while i know i could do this programiticly in LINQ. I started thinking about solutions that would scale if this were a vary large data set. I'm building my experieance with SQL and believe there is a way to get the result with out performing an insert.
What I have is data that looks like this:
ids type total
A01 x 1
A01 x 2
A01 x 3
A01 y 4
B01 y 2
B01 x 3
B01 y 1
C01 x 1
C01 y 2
C01 x 5
C01 y 6
What I want is data that looks like this:
id x total y total
A01 6 4
B01 3 3
C01 6 8
I's my belief incorrect?

...
SUM(CASE type WHEN'x' THEN total ELSE 0 END),
SUM(CASE type WHEN 'y' THEN total ELSE 0 END)
...
Group by
Id
Sorry hard to give full answer on phone

This is called a pivot table, and there are a number of ways to accomplish it.
If you're using SQL Server 2005 or later, the PIVOT operator (MSDN) is a neat option:
select id, [x], [y]
from temp d
PIVOT ( sum(total) for type in ([x],[y]) ) p

Related

calculating median to output similar results to over partition

i have a large table, here is a snippet of how it looks like
name class brand rating
12 d 1 3.8
22 d 1 3.9
33 a 2 1.1
12 d 1 2.3
12 a 3 3.4
44 b 1 9.8
22 c 2 3.0
i calculated for the average of the rating doing the below
select avg(rating) over(partition by name,class,brand) as avg_rating from df
i'm aware that postgres doesn't have a median function but i would like to calculate for that column and have the output in a similar structure to that of my window function for average
in case of even number of rows, i would like the average number between the middle two numbers
To get the median, you should use percentile_cont
SELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY rating) FROM df;

select all columns with suffix _test in q kdb

I have a partitioned table, similar to below table:
q)t:([]date:3#2019.01.01; a:1 2 3; a_test:2 3 4; b_test:3 4 5; c: 6 7 8);
date a a_test b_test c
----------------------------
2019.01.01 1 2 3 6
2019.01.01 2 3 4 7
2019.01.01 3 4 5 8
Now, I want to fetch date column and all columns have names with suffix "_test" from table t.
Expected output:
date a_test b_test
------------------------
2019.01.01 2 3
2019.01.01 3 4
2019.01.01 4 5
In my original table, there are more than 100 columns with name having _test so below is not a practical solution in this case.
q)select date, a_test, b_test from t where date=2019.01.01
I tried various options like below, but of no use:
q)delete all except date, *_test from select from t where date=2019.01.01
If the columns you are selecting are variable then you should use a functional qSQL statement to perform the query. The following can be used in your case
q)query:{[tab;dt;c]?[tab;enlist (=;`date;dt);0b;(`date,c)!`date,c]}
q)query[t;2019.01.01;cols[t] where cols[t] like "*_*"]
date a_test b_test
------------------------
2019.01.01 2 3
2019.01.01 3 4
2019.01.01 4 5
In order to craft a particular functional statement, you can parse your query, putting dummy columns in place if you aren't sure what they should be
q)parse "select date,c1,c2 from tab where date=dt"
?
`tab
,,(=;`date;`dt)
0b
`date`c1`c2!`date`c1`c2
A functional select is probably the best way to go here if you require adding further filters.
?[`t;();0b;{x!x}`date,exec c from meta t where c like "*_test"]
The functional form of any select quesry can be obtained by using the -5! operator on any SQL style statement.
In the example below I have created a table with 20 fields, each one beginning with either a or b.
I then use the functional form to define which fields I want.
q)tab:{[x] enlist x!count[x]#0}`$"_" sv ' raze string `a`b,/:\:til 10
q){[t;s]?[t;();0b;{[x] x!x} cols[t] where cols[t] like s]}[tab;"b*"]
b_0 b_1 b_2 b_3 b_4 b_5 b_6 b_7 b_8 b_9
---------------------------------------
0 0 0 0 0 0 0 0 0 0
q){[t;s]?[t;();0b;{[x] x!x} cols[t] where cols[t] like s]}[tab;"a*"]
a_0 a_1 a_2 a_3 a_4 a_5 a_6 a_7 a_8 a_9
---------------------------------------
0 0 0 0 0 0 0 0 0 0
q)-5!" select a,b from c"
?
`c
()
0b
`a`b!`a`b
Alternatively, if I don't require any filtering I can use the # operator as in below:
{[x;s] (cols[x] where cols[x] like s)#x}[ tab;"a*"]

PostgreSQL: Count from x to y

How do I count in PostgreSQL from X to Y where X and Y come from table fields.
Similar to how a for loop works.
I tried to use ranges.
Use generate_series:
demo:db<>fiddle
It is not quiet clear what your data looks like:
A: You have one table with two columns x and y and exactly one row:
x | y
--+--
2 | 5
B: You have one table with two columns x and y and more than one row:
x | y
--+--
2 | 5
3 |10
It's not quiet clear what you mean with "count":
I.: You want one row per element:
count
-----
2
3
4
5
II.: You want an array of all elements:
count
-----
{2,3,4,5}
A.I: You have a table with two columns x and y with exactly one row and want one row per element:
SELECT generate_series(x, y)
FROM values;
Result as seen in I. above
B.I: You have many rows:
Same query, result is the union of the generated rows:
count
-----
2
3
4
5
3
4
5
6
7
8
9
10
A.II: One row, want an array:
You have to group your generated series
SELECT array_agg(gs)
FROM (
SELECT x, generate_series(x, y) as gs
FROM values
) s
GROUP BY x
Result as seen in II.
B.II: Many rows, want an array:
Same query, result looks like:
count
------------------
{2,3,4,5}
{3,4,5,6,7,8,9,10}

PostgreSQL window function & difference between dates

Suppose I have data formatted in the following way (FYI, total row count is over 30K):
customer_id order_date order_rank
A 2017-02-19 1
A 2017-02-24 2
A 2017-03-31 3
A 2017-07-03 4
A 2017-08-10 5
B 2016-04-24 1
B 2016-04-30 2
C 2016-07-18 1
C 2016-09-01 2
C 2016-09-13 3
I need a 4th column, let's call it days_since_last_order which, in the case where order_rank = 1 then 0 else calculate the number of days since the previous order (with rank n-1).
So, the above would return:
customer_id order_date order_rank days_since_last_order
A 2017-02-19 1 0
A 2017-02-24 2 5
A 2017-03-31 3 35
A 2017-07-03 4 94
A 2017-08-10 5 38
B 2016-04-24 1 0
B 2016-04-30 2 6
C 2016-07-18 1 79
C 2016-09-01 2 45
C 2016-09-13 3 12
Is there an easier way to calculate the above with a window function (or similar) rather than join the entire dataset against itself (eg. on A.order_rank = B.order_rank - 1) and doing the calc?
Thanks!
use the lag window function
SELECT
customer_id
, order_date
, order_rank
, COALESCE(
DATE(order_date)
- DATE(LAG(order_date) OVER (PARTITION BY customer_id ORDER BY order_date))
, 0)
FROM <table_name>

Get Data from 2 Tables using Join

I have 2 tables :
1. transfer
2. data
in table data 2 records :
id name
1. 2 PQR
2. 3 XYZ
in table transfer 5 records :
id to from amount type
1. 1 2 3 100.00 C
2. 2 3 2 200.00 C
3. 3 2 3 150.00 D
4. 4 3 2 150.00 C
5. 5 2 3 300.00 D
now I want to form query that will take 2 in where condition and give me result
from transfer table that when 2 is in to column then from data should be shown
and when 2 is in from column then to data should be print.
And in result I want other columns that are amount and type.
I want data using join (Any), I am totally confused that how to perform this task.
Expected Result :
from/to amount type
3 100.00 C
3 200.00 C
3 150.00 D
3 300.00 D
Any Guidance on this..
Try Like this
select
case when "from"=2 then "to" when "to"=2 then "from" end "from/to"
,amount,type from transfer
Out put is
form/to amount type
3 100 C
3 200 C
3 150 D
3 150 C
3 100 D
OR
select case when "from"=2 then d.name when "to"=2 then data.name end "from/to",
amount,type from transfer inner join data on ("to"=data.id)
inner join data as d on("from"=d.id)
Out put is
form/to amount type
XYZ 100 C
XYZ 200 C
XYZ 150 D
XYZ 150 C
XYZ 100 D
ADDITION:
prove of working query: http://ideone.com/64kIov