How do I do a second group (rank) within a set of records? - snowflake-cloud-data-platform

Here is an example of the data-
Example
First rank is done based on event_time ascending.
After the first ranking I need record 2 to record 6 be ranked as 1 and rec7 to 17 as 2. Can this be achieved in snowflake db?

you can use the case statement and have the values as follows.
# I need record 2 to record 6 be ranked as 1 and rec7 to 17 as 2.
select
column1,
case
when column1 > 2 and column1 < 6 then 1
when column1 > 6 and column1 < 18 then '2'
else '0'
end as new_col
from values (3), (4), (3), (17);

Related

Classifying rows into a grouping column that shows the data is related to prior rows

I have a set of data that I want to classify into groups based on a prior record id existing on the newer rows. The initial record of the group has a prior sequence id = 0.
The data is as follows:
customer id
sequence id
prior_sequence id
1
1
0
1
2
1
1
3
2
2
4
0
2
5
4
2
6
0
2
7
6
Ideally, I would like to create the following grouping column and yield the following results:
customer id
sequence id
prior sequence id
grouping
1
1
0
1
1
2
1
1
1
3
2
1
2
4
0
2
2
5
4
2
2
6
0
3
2
7
6
3
I've attempted to utilize island gap logic utilizing the ROW_NUMBER() function. However, I have been unsuccessful in doing so. I suspect the need here is more along the lines of a recursive CTE, which I am attempting at the moment.
I agree that a recursive CTE will do the job. Something like:
WITH reccte AS
(
/*query that determines starting point for recursion
*
* In this case we want all records with no prior_sequence_id
*/
SELECT
customer_id,
sequence_id,
prior_sequence_id,
/*establish grouping*/
ROW_NUMBER() OVER (ORDER BY sequence_id) as grouping
FROM yourtable
WHERE prior_sequence_id = 0
UNION
/*join the recursive CTe back to the table and iterate*/
SELECT
yourtable.customer_id,
yourtable.sequence_id,
yourtable.prior_sequence_id,
reccte.grouping
FROM reccte
INNER JOIN yourtable ON reccte.sequence_id = yourtable.prior_sequence_id
)
SELECT * FROM reccte;
It looks like you could use a simple correlated query, at least given your sample data:
select *, (
select Sum(Iif(prior_sequence_id = 0, 1, 0))
from t t2
where t2.sequence_id <= t.sequence_id
) Grouping
from t;
See Example Fiddle

How to split Row into multiple column using T-SQL

There are three column,wherever D_ID=13,value_amount holds value for mode of payment and wherever D_ID=10,value_amount holds value for amount.
ID D_ID Value_amount
1 13 2
1 13 2
1 10 1500
1 10 1500
2 13 1
2 13 1
2 10 2000
2 10 2000
Now I have to add two more columns amount and mode_of_payment and result should come like below
ID amount mode_of_payment
1 1500 2
1 1500 2
2 2000 1
2 2000 1
This is too long for a comment.
Simply put, your data is severely flawed. For the example data you've given, you're "ok", because the rows have the same values to the same ID, but what about when they don't? Let's assume, for example, we have data that looks like this:
ID D_ID Value_amount
1 13 1 --1
1 13 2 --2
1 10 1500 --3
1 10 1000 --4
2 13 1 --5
2 13 2 --6
2 10 2000 --7
2 10 3000 --8
I've added a "row number" next to data, for demonstration purposes only.
Here, what row is row "1" related to? Row "3" or row "4"? How do you know? There's no always ascending value in your data, so row "3" could just as easily be row "4". In fact, if we were to order the data using ID ASC, D_ID DESC, Value_amount ASC then rows 3 and 4 would "swap" in order. This could mean that when you attempt a solution, the order in wrong.
Tables aren't stored in any particular order, that are unordered. What determines the order the data is presented in is the ORDER BY clause, and if you don't have a value to define that "order", then that "order" is lost as soon as you INSERT it.
If, however, we add a always ascending value into your data, you can achieve this.
CREATE TABLE dbo.YourTable (UID int IDENTITY,
ID int,
DID int,
Value_amount int);
GO
INSERT INTO dbo.YourTable (ID, DID, Value_amount)
VALUES (1,13,1 ),
(1,13,2 ),
(1,10,1500),
(1,10,1000),
(2,13,1 ),
(2,13,2 ),
(2,10,2000),
(2,10,3000);
GO
WITH RNs AS(
SELECT ID,
DID,
Value_amount,
ROW_NUMBER() OVER (PARTITION BY ID, DID ORDER BY UID ASC) AS RN
FROM dbo.YourTable)
SELECT ID,
MAX(CASE DID WHEN 13 THEN Value_Amount END) AS Amount,
MAX(CASE DID WHEN 10 THEN Value_Amount END) AS PaymentMode
FROM RNs
GROUP BY RN,
ID;
GO
DROP TABLE dbo.YourTable;
Of course, you need to fix your design to implement this, but you need to do that anyway.

SQL Server / Oracle: How to increase index column dependent on another column?

Given the following table:
Column1 Column2 idx
-------------------
1 1 0
2 1 0
3 2 0
4 3 0
5 3 0
1 3 0
How could I increase the idx column dependent on column2 in SQL Server and Oracle with an UPDATE statement?
I would like to have:
Column1 Column2 idx
--------------------
1 1 0
2 1 1
3 2 0
4 3 0
5 3 1
1 3 2
Thank you!
This (or similar) approach should work for both:
;with x as (
select idx, row_number() over(partition by Column2 order by Column1) as new_idx
from tbl
)
update x set idx = new_idx
(Here I assume that there is a typo in 6th row for Column1 - if not, there should be something else for ordering)
With Oracle you need a MERGE statement for this:
merge into x using (
select rowid as rid,
row_number() over(partition by Column2 order by Column1) as new_idx
from tbl
) t on (t.rid = x.rowid)
when matched then
set idx = t.new_idx;
Instead of using rowid you can replace the join with the primary key columns of the table.

How to avoid duplicate values in joining two or three tables?

I have this two tables and I want to join their two ID's.
Household Info
1
2
3
Household Members
1
1
1
2
3
3
3
3
3
The values is repeating over and over again, as you have noticed on my screenshot. The output I want is, I want a query of this:
Household Info.HID Household Members.HID
1 1
1
1
2 2
3 3
3
3
3
3
Since in the Table Household Info there are only 3 HID while the table Household Members there are three:1, one:2, and five:3
Hope you can help me on this one :3
EDITED: I am using Microsoft Access as RDBMS
For an RDBMS which supports CTE...
DECLARE #Household TABLE
( Household VARCHAR(10))
;
INSERT INTO #Household
( Household )
VALUES
(1),
(2),
(3)
;
declare #HouseholdMembers TABLE
( HouseholdMembers VARCHAR(10))
;
INSERT INTO #HouseholdMembers
( HouseholdMembers )
VALUES
(1),
(1),
(1),
(2),
(3),
(3),
(3),
(3),
(3)
;
Select
CASE WHEN RN = 1 THEN Household ELSE '' END Household,
HouseholdMembers
from (
select h.Household,
hm.HouseholdMembers,
ROW_NUMBER()OVER(PARTITION BY hm.HouseholdMembers ORDER BY h.Household)RN from #Household h
LEFT JOIN #HouseholdMembers hm
ON hm.HouseholdMembers = h.Household)T
You didn't mention what are you using as RDBMS.
I think that you can use pivot for your case:
http://www.codeproject.com/Tips/500811/Simple-Way-To-Use-Pivot-In-SQL-Query
or to use grouping:
select c2, c3
, sum( case when no_of_days <= 7 then 1 else 0 end) as dlt8
, sum( case when no_of_days between 8 and 14 then 1 else 0 end) as d8to14
, sum( case when no_of_days between 15 and 21 then 1 else 0 end) as d15to21
, sum( case when no_of_days between 22 and 27 then 1 else 0 end) as d22to27
from mytable
group by c2, c3
order by c2, c3;
Here you can find similar answer to your question:
Dynamic alternative to pivot with CASE and GROUP BY
Edit 1
If you need something like this:
SubjectID StudentName
---------- -------------
1 Mary
1 John
1 Sam
2 Alaina
2 Edward
Result I expected was:
SubjectID StudentName
---------- -------------
1 Mary, John, Sam
2 Alaina, Edward
you can check this example:
Concatenate many rows into a single text string?
Edit 2
And the last option that I can remember is this one. It's for MySQL but you can reuse the logic:
MySQL JOIN - Return NULL for duplicate results in left table

Get first value above current (stored procedure)

Currently I'm working on a stored procedure to update the sort order of a table. The idea is to make sure that the correct rows are swapped.
INPUT: ToMoveID INT, Up BIT (1 up, 0 down)
SERVER: MSSQL 2012
example to use:
ID SortOrder UseForSwap
1 1 Yes
2 NULL No
3 2 Yes
4 NULL No
5 3 Yes
The idea is to put the row with ID 5 higher, the ID of 3 is unkown at this point. How Can i get the ID of the row with te first sortorder higher as the current?
Sample values: TomoveID = 5, Up = 1
After sorting the result shoud be:
ID SortOrder UseForSwap
1 1 Yes
2 NULL No
3 3 Yes
4 NULL No
5 2 Yes
Thanks in advance
You can search for a row with the biggest SortOrder that is less than SortOrder of ID 5 row in this way:
SELECT TOP 1
tbl.ID
FROM YourTable tbl
WHERE tbl.SortOrder < (SELECT SortOrder FROM YourTable tbl2 WHERE tbl2.ID = 5)
ORDER BY
tbl.SortOrder DESC

Resources