I want to retrieve rows from table having MAX(col), but MAX(col) return multiple rows if values at col has same data.
I have 2 tables as below:
**Table1**
row_id INTEGER (Primary key auto incremented),
name TEXT
**Table2**
row_id INTEGER (Primary key auto incremented),
ref_id INTEGER (Foreign key of Table1(row_id)),
date_in_long TEXT,
data TEXT
Following query I am performing to get rows having MAX(date_in_long), expecting single latest entered rows.
SELECT DISTINCT a.name, b.row_id, b.ref_id, b.date_in_long, b.data
FROM Table1 a, Table2 b
WHERE a.row_id=b.ref_id
AND b.date_in_long =
(SELECT MAX(c.date_in_long)
FROM Table2 c
WHERE c.ref_id=a.row_id
)
Output result would be perfect if date_in_long is having different values against ref_id.. but it returns multiple rows is values are same.
Example
Table1:
row_id name
1 aparna
2 user1
3 XYZ
Table2:
row_id ref_id date_in_long data
1 1 98 data1 for aparna
2 1 100 data2 for aparna
3 1 100 data3 for aparna
4 2 200 data1 for user1
5 2 300 data2 for user1
6 3 100 data1 for XYZ
Result of above query:
row_id ref_id name date_in_long data
2 1 aparna 100 data2 for aparna
3 1 aparna 100 data3 for aparna
5 2 user1 300 data2 for user1
6 3 XYZ 100 data1 for XYZ
Expected result should be:
row_id ref_id name date_in_long data
3 1 aparna 100 data3 for aparna
5 2 user1 300 data3 for user1
6 3 XYZ 100 data1 for XYZ
Please let me know how issue in above query.
Adding below condition(As solution provided by Alexandar with this post) excluding some rows
AND
b.row_id = (Select MAX(c.row_id) from Table2 c where c.ref_id = b.ref_id)
Output after adding above row_id condition:
row_id ref_id name date_in_long data
3 1 aparna 100 data3 for aparna
6 3 XYZ 100 data1 for XYZ
No rows for USER1.
Please let me know how to solve this query.
Thank you,
Regards,
Aparna
The issue is that the "distinct" keyword doesn't mean "return rows where every value is different from every other row", it means "return rows that are in some way different from each other row".
So even though row_id 2 and 3 have the same ref_id, they have a different row_id and data column- Hence, they're unique rows.
One option is to add an extra condition so that only the max row_id for a specific ref-id is respected.
The added condition would look something like this.
AND
b.row_id = (Select MAX(c.row_id) from Table2 c where c.ref_id = b.ref_id)
Following query solve my issue.
SELECT a.name, b.row_id, b.ref_id, b.date_in_long, b.data, MAX(date_in_long)
FROM Table1 a INNER JOIN Table2 b
ON a.row_id=b.ref_id
GROUP BY a.row_id
Thank you,
Regards,
Aparna
Related
I'm trying to execute the following sqlite command to copy some values in a table:
INSERT OR IGNORE INTO table (column1, column2) VALUES((SELECT DISTINCT column1 FROM table WHERE column2 = '2'), 1);
What I want is for the 1 to be used for all the SELECTed rows, but it's only used once. How do I fix that?
I was thinking using a temp table with the default value to what I want. I know temp tables are used for complex queries, but it feels like this isn't that complicated and there could be an easier solution to this.
Example:
I want the following table...
column1 column2
1 2
4 2
5 3
4 4
...to become the following table...
column1 column2
1 2
4 2
5 3
4 4
1 1
4 1
Looks like you want to put the fixed column2 value in the select:
INSERT OR IGNORE INTO table (column1, column2) SELECT DISTINCT column1, 1 FROM table WHERE column2 = '2';
Also note the absence of VALUES.
My table tbl1 looks like this (SQLFiddle):
id col1 col2 col3
1 0 1 0
2 1 0 0
3 0 0 1
4 1 1 1
5 0 0 0
My requirement is that I get some positive number from the user for each column, and I need to update the rows of a particular column if they contain zero, and finally I should count the number of rows updated and the difference between the user input and the updated count I should add to the last row.
Let me explain with example:
Say user inputs 10 for col1. col1 has 3 rows containing zero so I will update them to 1, and finally the diff i.e. (10 - 3 = 7) I should update in the last row.
After the update I expect the table to look like this:
id col1 col2 col3
1 1 1 0
2 1 0 0
3 1 0 1
4 1 1 1
5 8 0 0
update tbl1 set col1=1 where id in (select id from tbl1 where col1=0 limit 10)
The above query updates all 0s to 1, but how do I add the remaining to last row?
To accomplish your task, I would use 2 update queries. The first one would be the query you already have:
UPDATE tbl1 SET col1=1 WHERE id IN (SELECT id FROM tbl1 WHERE col1=0 LIMIT 10);
I would save the result from the first update query in a variable (since it returns the number of rows affected), and use that result in my next query:
UPDATE tbl1 SET col1 = col1+updateResult ORDER BY id DESC LIMIT 1;
(updateResult is what is returned from the first update query).
I hope this helps.
First, find out how many rows will be updated:
SELECT COUNT(*)
FROM tbl1
WHERE id IN (SELECT id
FROM tbl1
WHERE col1 = 0
LIMIT 10)
The update those:
UPDATE tbl1
SET col1 = 1
WHERE id IN (SELECT id
FROM tbl1
WHERE col1 = 0
ORDER BY id
LIMIT 10)
(Without ORDER BY, some random set of ten rows would be updated.)
Then update the last row:
UPDATE tbl1
SET col1 = col1 + (10 - ResultFromAbove)
WHERE id = (SELECT MAX(id)
FROM tbl1)
To ensure consistency, do everything in a single transaction.
i have two tables:
Acounts:
ID Name
1 cash
2 bank
3 credit card
Transactions
ID accounts_id details income expenses
1 1 abc 1000 0
2 1 xyz 0 500
3 2 avc 200 0
what i want is to get the sum of income and expenses column for all the accounts in account table (even if there is not record in the transaction table for that account_id)
required output:
account_id total_income total_expenses
1 1000 500
2 200 0
3 0 0
what i am trying in sql:
select account_id,coalesce (sum(income),0) as total_income,coalesce(sum(expenses),0) as total_expenses from transactions where account_id in (select id as accounts_id from accounts) group by account_id
what the above query gives:
account_id total_income total_expenses
1 1000 500
2 200 0
account with ID=3 is not included in the result..
i know i am doing something wrong.. or may be completely wrong..
Thanks in advance.
You need to get all the accounts in the account table. To do that, you need a join, specifically an outer join:
select a.account_id, coalesce(sum(t.income),0) as total_income,
coalesce(sum(t.expenses),0) as total_expenses
from accounts a left join
transactions t
on a.account_id = t.account_id
group by a.account_id;
Your attempt to do this in the where clause is counterintuitive. The where clause filters values, so it reduces the number of rows; it cannot increase the number.
WITH TEMP AS
(
SELECT A.ID,T.*
FROM ACCOUNTS A INNER JOIN TRANSACTIONS T
ON A.ID=T.ID
)
SELECT ACCOUNT_ID,SUM(INCOME) AS INCOME,SUM(EXPENSE) AS EXPENSE FROM TEMP
GROUP BY ACCOUNT_ID;
I have a SQLite table defined this way:
CREATE TABLE Points(value INTEGER, player INTEGER, match INTEGER)
In the execution, I may have several identical columns, and I want a call which only deletes one, not all of them nor keeping just one. Is there any SQL call to do that?
An example to explain myself clearer:
value player match
1 2 3
1 3 3
1 2 3
2 2 3
1 2 3
1 2 3
1 3 3
db.delete("Points", "value = 1, player = 2, match = 3", null); //pseudo-code for the deletion
db.delete("Points", "value = 1, player = 3, match = 3", null);
value player match
1 2 3
2 2 3
1 2 3
1 2 3
1 3 3
I think db.delete("Points", "value = 1, player = 3, match = 3", null); will delete ALL columns which match the where clauses, am I right?
The delete statement you wrote will indeed delete all matching rows.
Try to use the built-in column ROWID, read the first line, save the rowid, and then delete where ROWID= the value you selected.
Try this
String _val=""+1;
String _player=""+3;
String _match=""+3;
db.delete(TABLE_NAME,"value=? AND player=? AND match=?",new String[] {_val,_player,_match});
The usual way to do this is to assign every table a unique identifier for each row. Like this:
CREATE TABLE Points(Id INTEGER PRIMARY KEY, value INTEGER, player INTEGER, match INTEGER);
Then you can use a subquery to find the one row you want to delete:
DELETE FROM Points WHERE Id =(SELECT MIN(Id) FROM Points WHERE value=1 AND player=2 and match=3);
This example deletes the oldest record entered first (the oldest has the lowest unique key Id)
Hello I have a table with that structure:
ID VALUE
1 3
2 5
3 12
if I query select id,value,value+5 from table. Thats the result
ID VALUE NEW_VALUE
1 3 8
2 5 10
3 12 17
And what I want to make a query indicating the id and the new value that return the whole table but with a 3rd column indicating the new values after inserting. for example for myQuery(id=2,value=8)
ID VALUE NEW_VALUE
1 3 3
2 5 8
3 12 12
Is posible to do that in the same query?
YOu can use the WHERE clause to select only the rows you want ("...if the student has the given id..."):
update T
set col3 = col2 + 5
where id = 2
Of course, col3 would have to exist before you can update it. So you will either have to issue an ALTER-TABLE statement (if your implementation supports it) or recreate the table with the desired columns, import the original data (INSERT INTO YOURNEWTABLE...SELECT ... from YOUROLDTABLE) and then update col3.
If you don't want to "persist" this third column but only need it to be displayed when you query:
select id, col2, col2 + 5 as myComputedValue
from T
where id = 2
Finally, if you want to display all rows but change the addend conditionally (add zero to col2 when the id is not one of the ones you desire but add 5 when it is) then you can use the CASE statement.