I have a table of values that I want to rotate the values of.
For instance, suppose I have the given (sub) table:
id | value | other columns...
---+-------+---
1 | A | ...
29 | B |
37 | C |
56 | D |
I want to rotate the values so that the final state of the table is:
id | value | other columns...
---+-------+---
1 | B | ...
29 | C |
37 | D |
56 | A |
I know all the ids which should take part in the rotate. However, I'm not sure how I would use this knowledge to update the values. Something like this is not valid SQL:
UPDATE table SET value=('B','C','D','A') WHERE id IN (1,29,37,56)
You could use a CASE expression:
UPDATE MyTable
SET value = CASE id
WHEN 1 THEN 'B'
WHEN 29 THEN 'C'
WHEN 37 THEN 'D'
WHEN 56 THEN 'A'
END
WHERE id IN (1, 29, 37, 56);
Related
I have hierarchical data as follows.
|Serial No | Primary Flag |Prev SerialNo|
| 101 | 1 | 56 |
| 56 | 0 | NULL |
| 505 | 0 | NULL |
| 223 | 1 | 156 |
| 156 | 0 | 93 |
| 93 | 0 | 42 |
42 | 0 | NULL |
First two rows are related by Previous serial number when primary flag, so total counts in their hierarchy is 2
Third row is not related to any thing since Previous serial number is NULL., so total count is 0.
Fourth row is related to below 3 records, so total count is 4.
I need a query to find the total related counts for rows when Primary flag is 1.How can I achieve this in Teradata?
Assuming you don't want to return a row for Serial_No 505, you can use a recursive query and aggregation:
WITH RECURSIVE r AS (
SELECT h.Serial_No AS Primary_SerialNo, h.Serial_No, h.Prev_SerialNo, 1 (INTEGER) as Level
FROM hierTbl h WHERE h.Primary_Flag=1
UNION ALL
SELECT r.Primary_SerialNo, h.Serial_No, h.Prev_SerialNo, r.Level+1
FROM hierTbl h JOIN r ON r.Prev_SerialNo = h.Serial_No
)
Select Primary_SerialNo, MAX(Level) as Related
FROM r GROUP BY 1;
Let's say I have a table:
+--------------+--------------+------+-----+
| ID | Score | email | add |
+--------------+--------------+------+-----+
| 123 | 88 | 123#gmail.com | somewhere |
| 456 | 77 | 123#gmail.com | somewhere |
| 789 | 88 | 123#gmail.com | somewhere |
| 111 | 77 |123#gmail.com | somewhere |
| 555 | 77 | 123#gmail.com | somewhere |
|444 | 88 | 123#gmail.com | somewhere
| 222 | 77 | 123#gmail.com | somewhere |
| 333 | 88 |123#gmail.com | somewhere |
My question is it possible to select Score column and ONLY print out first 3 88 and 77 Score?
I tried but it seems only give me 3 88 scores only
SELECT Score
FROM Table_Name
WHERE Score = '88' OR Score = '77'
LIMIT 3
First filter the table so that only the rows with the scores that you want are returned and then use ROW_NUMBER() window function to rank the rows of each Score based on ID so that you can filter out the rows that exceed the first 3 of each group:
SELECT ID, Score, email, add
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Score ORDER BY ID) rn
FROM Table_Name
WHERE Score = '88' OR Score = '77'
)
WHERE rn <= 3;
For versions of SQLite prior to 3.25.0 that do not support window functions use a correlated subquery:
SELECT t1.*
FROM Table_Name t1
WHERE t1.Score = '88' OR t1.Score = '77'
AND (SELECT COUNT(*) FROM Table_Name t2 WHERE t2.Score = t1.Score AND t2.ID <= t1.ID) <= 3;
I have a database that I don't control the source of directly and results in errant '0' entries which mess up generated graphs with these drops to zero. I am able to manipulate the data after the fact and update that database.
It is acceptable that the last known good value can be used instead and so I am trying to make a general query that will remove all the zeros and populate it with the last known value.
Luckily, every entry includes the ID of the last entry and so it is a matter of simply looking back and grabbing it.
I have got very close to a final answer, but instead of updating with the last good value, it just uses the first value over and over again.
dummy data
CREATE TABLE tbl(id INT,r INT,oid INT);
INSERT INTO tbl VALUES(1,10,0);
INSERT INTO tbl VALUES(2,20,1);
INSERT INTO tbl VALUES(3,0,2);
INSERT INTO tbl VALUES(4,40,3);
INSERT INTO tbl VALUES(5,50,4);
INSERT INTO tbl VALUES(6,0,5);
INSERT INTO tbl VALUES(7,70,6);
INSERT INTO tbl VALUES(8,80,7);
SELECT * FROM tbl;
OUTPUT:
| id| r |oid|
|---|----|---|
| 1 | 10 | 0 |
| 2 | 20 | 1 |
| 3 | 0 | 2 | ** NEEDS FIXING
| 4 | 40 | 3 |
| 5 | 50 | 4 |
| 6 | 0 | 5 | ** NEEDS UPDATE
| 7 | 70 | 6 |
| 8 | 80 | 7 |
I have worked several queries to get results around what I am after:
All zero entries:
SELECT * FROM tbl WHERE r = 0;
OUTPUT:
| id | r | oid |
|----|----|-----|
| 3 | 0 | 2 |
| 6 | 0 | 5 |
Output only the those rows with the preceding good row
SELECT * FROM tbl WHERE A in (
SELECT id FROM tbl WHERE r = 0
UNION
SELECT oid FROM tbl WHERE r = 0
)
OUTPUT:
| id| r |oid|
|---|----|---|
| 2 | 20 | 1 |
| 3 | 0 | 2 |
| 5 | 50 | 4 |
| 6 | 0 | 5 |
Almost works
This is as close as I have got, it does change all the zero's, but it changes them all to the value of the first lookup
UPDATE tbl
SET r = (SELECT r
FROM tbl
WHERE id in (SELECT oid
FROM tbl
WHERE r = 0)
) WHERE r = 0 ;
OUTPUT:
| id| r |oid|
|---|----|---|
| 1 | 10 | 0 |
| 2 | 20 | 1 |
| 3 | 20 | 2 | ** GOOD
| 4 | 40 | 3 |
| 5 | 50 | 4 |
| 6 | 20 | 5 | ** BAD, should be 50
| 7 | 70 | 6 |
| 8 | 80 | 7 |
If it helps, I created this fiddle here that I've been playing with:
http://sqlfiddle.com/#!5/8afff/1
For this sample data all you have to do is use the correct correlated subquery that returns the value of r from the row with id equal to the current oid in the WHERE clause:
UPDATE tbl AS t
SET r = (SELECT tt.r FROM tbl tt WHERE tt.id = t.oid)
WHERE t.r = 0;
See the demo.
I have the following table in an sqlite database
+----+-------------+-------+
| ID | Week Number | Count |
+----+-------------+-------+
| 1 | 1 | 31 |
| 2 | 2 | 16 |
| 3 | 3 | 73 |
| 4 | 4 | 59 |
| 5 | 5 | 44 |
| 6 | 6 | 73 |
+----+-------------+-------+
I want to get the following table out. Where I get this weeks sales as one column and then the next column will be last weeks sales.
+-------------+-----------+-----------+
| Week Number | This_Week | Last_Week |
+-------------+-----------+-----------+
| 1 | 31 | null |
| 2 | 16 | 31 |
| 3 | 73 | 16 |
| 4 | 59 | 73 |
| 5 | 44 | 59 |
| 6 | 73 | 44 |
+-------------+-----------+-----------+
This is the select statement i was going to use:
select
id, week_number, count,
(select count from tempTable
where week_number = (week_number-1))
from
tempTable;
You are comparing values in two different rows. When you are just writing week_number, the database does not know which one you mean.
To refer to a column in a specific table, you have to prefix it with the table name: tempTable.week_number.
And if both tables have the same name, you have to rename at least one of them:
SELECT id,
week_number,
count AS This_Week,
(SELECT count
FROM tempTable AS T2
WHERE T2.week_number = tempTable.week_number - 1
) AS Last_Week
FROM tempTable;
In case of you want to take a query upon a same table twice, you have to put aliases on the original one and its replicated one to differentiate them
select a.week_number,a.count this_week,
(select b.count from tempTable b
where b.week_number=(a.week_number-1)) last_week
from tempTable a;
I'm looking for a way to do a "grand total" column across ALL groups in Impala.
It's easy to use window functions to obtain total of partitioned groups like this:
sum(x) over (partition by A)
however it does not appear that there is an expression to partition by 'all'. Is this a shortcoming in Impala? It looks like in postgress you can leave the over statement blank.
The partition clause is optional. You can write a query like this:
select sum(x) over () from t;
For example:
[localhost:21000] > select id, sum(id) over () from tbl;
+----+-------------------+
| id | sum(id) OVER(...) |
+----+-------------------+
| 0 | 28 |
| 1 | 28 |
| 2 | 28 |
| 3 | 28 |
| 6 | 28 |
| 7 | 28 |
| 4 | 28 |
| 5 | 28 |
+----+-------------------+
Fetched 8 row(s) in 0.08s