Let's say I have two tables as following:
+--------------+-------+
| ID | Score |
+--------------+-------
| 123 | 88 |
| 456 | 77 |
| 789 | 88 |
| 111 | 77 |
| 555 | 77 |
|444 | 88 |
| 222 | 77 |
| 333 | 88 |
SECOND TABLE:
+--------------+-----+
| ID |NAME | FScore |
+--------------+-------
| 123 |John | 106 |
| 456 |Aaron | 99 |
| 789 |Dan | 105 |
| 111 |Kevin | 200 |
| 555 |Tom | 100 |
| 444 |Jeff | 120 |
| 222 |Carl | 65 |
| 333 |Wayne | 101 |
I want to join two tables and based on FScore find out top 3 88 and top 3 77 rows like:
+--------------+--------------+------+-----+
| ID | Score | NAME | FScore |
+--------------+--------------+------+-----+
| 444 | 88 | Jeff | 120 |
| 123 | 88 | John | 106 |
| 789 | 88 | Dan | 105 |
Any helps are appreciated!
You can use a CTE that returns the joined tables and then filter the resultset with a correlated subquery:
WITH cte AS (
SELECT *
FROM table1 t1 INNER JOIN table2 t2
ON t2.ID = t1.ID
WHERE t1.Score IN ('77', '88')
)
SELECT c1.ID, c1.Score, c1.Name, c1.FScore
FROM cte c1
WHERE (SELECT COUNT(*) FROM cte c2 WHERE c2.Score = c1.Score AND c2.FScore >= c1.FScore) <= 3;
Or, with ROW_NUMBER() window function:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY t1.Score ORDER BY t2.FScore DESC) rn
FROM table1 t1 INNER JOIN table2 t2
ON t2.ID = t1.ID
WHERE t1.Score IN ('77', '88')
)
SELECT ID, Score, Name, FScore
FROM cte
WHERE rn <= 3;
See the demo.
Related
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 SQLite table just like this:
the table name is 'surat'
But i want to make id_ayat to be split into different rows using SQLite query, and expected result just like this:
_id|id_surat|id_ayat
---+--------+-------
3 | 2 | 112
3 | 2 | 213
3 | 3 | 19
3 | 3 | 83
3 | 3 | 85
3 | 3 | 102
is that possible? what query that i can use in SQLite format?
With a recursive CTE:
with recursive cte as (
select _id, id_surat, id_ayat,
id_ayat + 0 col
from tablename
union all
select _id, id_surat, trim(substr(id_ayat, length(col) + 2)),
trim(substr(id_ayat, length(col) + 2)) + 0
from cte
where instr(id_ayat, ',')
)
select _id, id_surat, col id_ayat
from cte
order by _id, id_surat
See the demo.
Results:
| _id | id_surat | id_ayat |
| --- | -------- | ------- |
| 3 | 2 | 112 |
| 3 | 2 | 213 |
| 3 | 3 | 19 |
| 3 | 3 | 83 |
| 3 | 3 | 85 |
| 3 | 3 | 102 |
I'm trying to compose an SQLite query and I've found a problem that's beyond my skillset. I'm trying to output columns that are based on the rows of another referenced table.
Food_List:
| food_id | name |
|---------|-----------|
| 1 | Apple |
| 2 | Orange |
| 3 | Pear |
Nutrient_Definition:
| nutrient_id | name |
|-------------|-----------|
| 21 | Carbs |
| 22 | Protein |
| 23 | Fat |
Nutrient_Data:
| food_id | nutrient_id | value |
|---------|-------------|-------|
| 1 | 21 | 50 |
| 1 | 22 | 24 |
| 1 | 23 | 63 |
| 2 | 22 | 12 |
| 2 | 23 | 95 |
| 3 | 21 | 66 |
| 3 | 22 | 87 |
| 3 | 23 | 38 |
Output:
| food_id | name | Carbs | Protein | Fat |
|---------|-----------|-------|---------|-----|
| 1 | Apple | 50 | 24 | 63 |
| 2 | Orange | | 12 | 95 |
| 3 | Pear | 66 | 87 | 38 |
(Note that Orange does not have a "Carbs" entry in the Nutrient_Data table)
I believe the following will do what you want :-
DROP TABLE IF EXISTS food_list;
CREATE TABLE IF NOT EXISTS food_list(food_id INTEGER PRIMARY KEY, name TEXT);
DROP TABLE IF EXISTS nutrient_definition;
CREATE TABLE IF NOT EXISTS nutrient_definition(nutrient_id INTEGER PRIMARY KEY, name TEXT);
DROP TABLE IF EXISTS nutrient_data;
CREATE TABLE IF NOT EXISTS nutrient_data(food_id INTEGER, nutrient_id INTEGER, value INTEGER);
INSERT INTO food_list (name) VALUES
('apple'),('orange'),('pear')
;
INSERT INTO nutrient_definition (name) VALUES
('carbs'),('protien'),('fat')
;
INSERT INTO nutrient_data VALUES
(1,1,50),(1,2,24),(1,3,63),
(2,2,12),(2,3,95),
(3,1,66),(3,2,87),(3,3,38)
;
SELECT food_list.food_id,food_list.name,
(
SELECT value
FROM nutrient_data
WHERE nutrient_data.food_id = food_list.food_id AND
nutrient_data.nutrient_id = (SELECT nutrient_definition.nutrient_id FROM nutrient_definition WHERE nutrient_definition.name = 'carbs')
),
(
SELECT value
FROM nutrient_data
WHERE nutrient_data.food_id = food_list.food_id AND
nutrient_data.nutrient_id = (SELECT nutrient_definition.nutrient_id FROM nutrient_definition WHERE nutrient_definition.name = 'protien')
),
(
SELECT value
FROM nutrient_data
WHERE nutrient_data.food_id = food_list.food_id AND
nutrient_data.nutrient_id = (SELECT nutrient_definition.nutrient_id FROM nutrient_definition WHERE nutrient_definition.name = 'fat')
)
FROM food_list
;
Results in :-
I want to use SELECT * from multiple tables table1 and table2 to get the output table which is nothing but table2 data appended to table1. How do I construct the SELECT * FROM statement ?
Table1:
id model datetime driver distance
---|-----|------------|--------|---------
1 | S | 04/03/2009 | john | 399
2 | X | 04/03/2009 | juliet | 244
3 | 3 | 04/03/2009 | borat | 555
Table2:
id model datetime driver distance
---|-----|------------|--------|---------
4 | 3 | 03/03/2009 | john | 300
5 | X | 03/03/2009 | juliet | 200
Desired output:
model datetime driver distance
-----|------------|--------|---------
S | 04/03/2009 | john | 399
X | 04/03/2009 | juliet | 244
3 | 04/03/2009 | borat | 555
3 | 03/03/2009 | john | 300
X | 03/03/2009 | juliet | 200
Try this out this might help you
SELECT table1.model, table1.datetime, table1.driver, table1.distance FROM table1
UNION ALL SELECT table2.model, table2.datetime, table2.driver, table2.distance FROM table2;
union statement get slow for fetching the large data from the db, you can use join here,
select * from table0 left join table2 on table0.b = table2.b where table2.col is not null
I have a table like this:
+----+----------+----------+----------+-----------+----------+----------+
| ID | AR_SCORE | ER_SCORE | FS_SCORE | CPF_SCORE | IF_SCORE | IS_SCORE |
+----+----------+----------+----------+-----------+----------+----------+
| 1 | 25 | 35 | 45 | 55 | 65 | 75 |
| 2 | 95 | 85 | 75 | 65 | 55 | 45 |
+----+----------+----------+----------+-----------+----------+----------+
And I need to extract this:
+----+----------+-------+
| ID | SCORE | VALUE |
+----+----------+-------+
| 1 | AR_SCORE | 25 |
| 1 | ER_SCORE | 35 |
| 2 | AR_SCORE | 95 |
+----+----------+-------+
I read many questions about how to use pivoting in oracle but I could not make it work.
The conversion from columns into rows is actually an UNPIVOT. Since you are using Oracle 11g there are a few ways that you can get the result.
The first way would be using a combination of SELECT yourcolumn FROM...UNION ALL:
select ID, 'AR_SCORE' as Score, AR_SCORE as value
from yourtable
union all
select ID, 'ER_SCORE' as Score, ER_SCORE as value
from yourtable
union all
select ID, 'FS_SCORE' as Score, FS_SCORE as value
from yourtable
union all
select ID, 'IF_SCORE' as Score, IF_SCORE as value
from yourtable
union all
select ID, 'IS_SCORE' as Score, IS_SCORE as value
from yourtable
order by id
See Demo. Using UNION ALL was how you needed to unpivot data prior to Oracle 11g, but starting in that version the UNPIVOT function was implemented. This will get you the same result with fewer lines of code:
select ID, Score, value
from yourtable
unpivot
(
value
for Score in (AR_SCORE, ER_SCORE, FS_SCORE, IF_SCORE, IS_SCORE)
) un
order by id
See Demo. Both will give a result:
| ID | SCORE | VALUE |
|----|----------|-------|
| 1 | AR_SCORE | 25 |
| 1 | FS_SCORE | 45 |
| 1 | IS_SCORE | 75 |
| 1 | IF_SCORE | 65 |
| 1 | ER_SCORE | 35 |
| 2 | FS_SCORE | 75 |
| 2 | IS_SCORE | 45 |
| 2 | ER_SCORE | 85 |
| 2 | IF_SCORE | 55 |
| 2 | AR_SCORE | 95 |