KDB select where - kdb

I have a table
t:flip `dt`id`data ! (`d1`d1`d2`d2`d3`d3; 0 1 0 1 0 1; 100 200 100 300 0 200)
and from some other query, I have a table
s:flip `dt`id ! (`d1`d2`d2`d3; 0 0 1 1)
How can I select from t such that it returns all entries where the combination of dt and id are in s, so return
flip `dt`id`data ! (`d1`d2`d2`d3; 0 0 1 1; 100 100 300 200)

You can use in on table to table ops so just create a table from your required columns in t and use in to search s for the corresponding records. As long as the table columns and types from the left argument and right argument are the same, then in will produce a boolean list as expected.
q)select from t where ([]dt;id) in s
dt id data
----------
d1 0 100
d2 0 100
d2 1 300
d3 1 200

Related

How to get the sum of a count derived column in PostgreSQL?

I have a table with a shipment_id, no_of_boxes, and no_of_pallets as shown below.
shipment_id
no_of_boxes
no_of_pallets
1
23
0
1
45
0
1
0
1
2
3
0
2
165
0
2
0
10
I want to sum the no_of_boxes, and no_of_pallets columns against their respective shipment_id. The columns no_of_boxes, and no_of_pallets are COUNT derived columns (calculated from a different table with JOINS).
I tried writing a subquery for this but didn't help. Below subquery is for no_of_boxes, a similar query was written for no_of_pallets.
SELECT SUM(no_of_boxes)
FROM (SELECT COUNT(si.shipment_item_id) AS no_of_boxes
FROM shipment_item AS si
JOIN shipment_item AS si
ON si.shipment_order_systemid = sho.system_id
JOIN shipping_unit AS su
ON su.system_id = si.shipping_unit_systemid
WHERE su.unit LIKE 'BOX'
GROUP BY si.shipment_item_id,
su.unit) t
My desired result is:
shipment_id
no_of_boxes
no_of_pallets
1
68
1
2
168
10
To get the result you want, use the following query:
SELECT shipment_id, sum(no_of_boxes), sum(no_of_pallets)
FROM shipments
GROUP BY shipment_id;

how do I write a proper query in kdb this case?

I would like to get all the groups that have a distinct price of 0 from my table, IE only if all prices are 0 in that group should it be returned.
My query & table look something like this.
tab:([]grp:`a`b`c`c`a`a`a;price:0 20 0 1 0 0 0)
select grp from tab where distinct price = 0
The output should only be `a since `a is the only group where all prices are 0.
Using an fby is one way to achieve the result here.
q)tab:([]grp:`a`b`c`c`a`a`a;price:0 20 0 1 0 0 0)
q)select from tab where 0=(max;abs price)fby grp
grp price
---------
a 0
a 0
a 0
a 0
q)distinct exec grp from tab where 0=(max;abs price)fby grp
,`a
Another approach:
q)where exec all 0=price by grp from tab
,`a

PostgreSQL - Update table with previous values ​from another table

I want to update a table with the sum of a second table
This is the table 'x' that I want to update. Has a starting value and a closing value:
id
op_date
initial_value
end_value
1
2020-02-01
0
0
1
2020-02-02
0
0
2
2020-02-01
0
0
2
2020-02-02
0
0
The table 'y' save the values ​​of the day:
id
op_date
value_day
1
2020-01-29
500
1
2020-02-01
100
1
2020-02-02
200
2
2020-01-29
750
2
2020-02-01
100
2
2020-02-02
250
I want the result to look like this:
id
op_date
initial_value
end_value
1
2020-02-01
500
600
1
2020-02-02
600
800
2
2020-02-01
750
850
2
2020-02-02
850
1100
I tried this script, but the process just runs it and doesn't finish it:
UPDATE x
SET
initial_value= (select sum(y.value_day)
from public.y where
y.op_date > '2020-11-01' and y.op_date < x.op_date
and y.id = x.id),
end_value= (select sum(y.value_day)
from public.y where
y.op_date between '2020-11-01' and x.op_date
and y.id = x.id);
You can use window function. To understand window function more you can look this link.
At first i am writing query to select the value.
select id,op_date,
sum(value_day) over (
partition by y.id
rows between unbounded preceding and current row
)-value_day as initial_value,
sum(value_day) over (
partition by y.id
rows between unbounded preceding and current row
) as end_value
from y
;
This is your update query.
UPDATE x
set initial_value=s_statement.initial_value,
end_value=s_statement.end_value
from
(select id,op_date,
sum(value_day) over (
partition by y.id
rows between unbounded preceding and current row
)-value_day as initial_value,
sum(value_day) over (
partition by y.id
rows between unbounded preceding and current row
) as end_value
from y) s_statement
where x.id=s_statement.id
and x.op_date=s_statement.op_date
;
Let me know if its ok with you.

Redshift - Get a value from one column A for each ID in the grouping ID column B based on max value in another column C

I have a sql problem (on Redshift) where I need to get the value from column index for each id in column id based on max value in column final_score and put this value in a new column fav_index. score2 equals to the value of score1 where index n = index n + 1, for example, for id = abc1, index = 0 and score1 = 10 the value of score2 will be the value of score1 where index = 1 and the value of final_score is the difference between score1 and score2.
It's easier if you look at below table score. This table score is a result of a sql query which is shown later below.
id index score1 score2 final_score
abc1 0 10 20 10
abc1 1 20 45 25
abc1 2 45 (null) (null)
abc2 0 5 10 5
abc2 1 10 (null) (null)
abc3 0 50 30 -20
abc3 1 30 (null) (null)
So, the resulting table containing column fav_index should look like this:
id index score1 score2 final_score fav_index
abc1 0 10 20 10 0
abc1 1 20 45 25 1
abc1 2 45 (null) (null) 0
abc2 0 5 10 5 0
abc2 1 10 (null) (null) 0
abc3 0 50 30 -20 0
abc3 1 30 (null) (null) 0
Below is the script to generate table score from table story:
select
m.id,
m.index,
max(m.max) as score1,
fmt.score2,
round(fmt.score2 - max(m.max), 1) as final_score
from
(select
sv.id,
case when sv.story_number % 2 = 0 then cast(sv.story_number / 2 - 1 as int) else cast(floor(sv.story_number/2) as int) end as index,
max(sv.score1)
from
story as sv
group by
sv.id,
index,
sv.score1
order by
sv.id,
index
) as m
left join
(select
sv.id,
case when sv.story_number % 2 = 0 then cast(sv.story_number / 2 - 1 as int) else cast(floor(sv.story_number/2) as int) end as index,
max(score1) as score2
from
story as sv
group by
id,
index
) as fmt
on
m.id = fmt.id
and
m.index = fmt.index - 1
group by
m.id,
m.index,
fmt.score2
Table story is as below:
id story_number score1
abc1 1 10
abc1 2 10
abc1 3 20
abc1 4 20
abc1 5 45
abc1 6 45
The only solution I can think of is to do something like,
select id, max(final_score) from score group by id
and then join it back to the long script above (which was used to generate table score). I really want to avoid writing such a long script to get just 1 extra column of information that I need.
Is there a better way to do this?
Thank you!
Update: answer in mysql is also accepted. thanks!
After spending more hours on this and asking people around, I finally figured out a solution by referring to this window function documentation - PostgreSQL https://www.postgresql.org/docs/9.1/static/tutorial-window.html
I basically added 2 x select statements at the top and 1 x where statement at the very bottom. The where statement is to take care of the rows where final_score = null because otherwise the rank() function will rank them as 1.
My code then becomes:
select
id, index, final_score, rank, case when rank = 1 then index else null end as fav_index
from
(select
id, index, final_score, rank() over (partition by id order by final_score desc)
from
(select
m.id,
m.index,
max(m.max) as score1,
fmt.score2,
round(fmt.score2 - max(m.max), 1) as final_score
from
(select
sv.id,
case when sv.story_number % 2 = 0 then cast(sv.story_number / 2 - 1 as int) else cast(floor(sv.story_number/2) as int) end as index,
max(sv.score1)
from
story as sv
group by
sv.id,
index,
sv.score1
order by
sv.id,
index
) as m
left join
(select
sv.id,
case when sv.story_number % 2 = 0 then cast(sv.story_number / 2 - 1 as int) else cast(floor(sv.story_number/2) as int) end as index,
max(score1) as score2
from
story as sv
group by
id,
index
) as fmt
on
m.id = fmt.id
and
m.index = fmt.index - 1
group by
m.id,
m.index,
fmt.score2)
where
final_score is not null)
And the result is as follows:
id index final_score rank fav_index
abc1 0 10 2 (null)
abc1 1 25 1 1
abc2 0 5 1 0
abc3 0 -20 1 0
Result is slightly different than what I stated in the question, however, the fav_index for each id is identified and this is what I needed really. Hope this might help someone. Cheers

How do I transpose columns into rows using tree in SQL? Is there any tree in sql command to transpose?

We are trying to output for each customer column should have 12 budgeted row entries for every month.
Scenario 1:
ie. Turn table data :
Name BudMnt1|BudMnt2|BudMnt3
cust1 0 0 0
cust2 0 0 0
cust3 2418 0 0
cust4 0 416 198
into this :
Name cust1| cust2| cust3| cust4
BudMnt1 0 0 24180 0
BudMnt2 0 0 0 416
BudMnt3 0 0 0 198
Scenario 2:
Includes Scenario 1 column as Budget+ additional column is sales solumn here
so, it becomes two column budget ,sales which needs to unpivot on single query structure.
ie. Turn table data :
Name JanSales|FebSales|MarSales
cust1 0 0 0
cust2 0 0 0
cust3 0 0 3
cust4 2 0 0
into this :
Name cust1|cust2|cust3|cust4
JanSales 0 0 0 2
Feb Sales 0 0 0 0
Mar Sales 0 0 3 0
Any HELP would be much appreciated !
This link may help you as a reference to your question:
https://social.msdn.microsoft.com/Forums/office/en-US/04346f7c-0923-432d-83c3-22bf759dea22/transpose-data-from-columns-into-rows-using-sql
This code works fine. Tasted it on sql server 2012.
SELECT NAME ,
budmtn ,
cust
INTO #temptable
FROM ( SELECT *
FROM tbl1
) AS result UNPIVOT ( cust FOR budmtn IN ( budmtn1, budmtn2, budmtn3 ) ) AS unpivotedtable
SELECT budmtn ,
cust1 ,
cust2 ,
cust3 ,
cust4
FROM #temptable PIVOT( SUM(cust) FOR NAME IN ( cust1, cust2, cust3, cust4 ) ) AS result