I have a table and I am trying to get the sum of Col A to 2 decimal places of all rows (there is an id column ID) that satisfies the following:
1) There is another row with a matching Col B
2) It has an unique pair of the values in Col C and Col D
Try this:
SELECT ROUND(SUM(ColA), 2) AS ColA_Sum
FROM datatable t
WHERE EXISTS (
SELECT 1
FROM datatable t2
WHERE t2.ID <> t.ID -- Another row must have different id
AND t2.ColB = t.ColB -- Matching Column B
)
AND EXISTS (
SELECT 1
FROM datatable t3
WHERE t3.ColC = t.ColC -- Same Column C
AND t3.ColD = t.ColD -- Same Column D
HAVING COUNT(*) = 1 -- Only 1 row with such values
)
I think it might be as simple as:
SELECT ROUND(SUM(t.cola), 2) AS cola_sum
FROM t
WHERE cola = colb
AND NOT EXISTS
(SELECT 1
FROM t t2
WHERE t2.colc = t.colc
AND t2.cold = t.cold
GROUP BY colc, cold
HAVING COUNT(*) > 1)
Check out the test here: http://rextester.com/BSVW57900
Related
I want to exclude from my populated query each row with the first occurrence of a value which appears in subsequent rows.
I've looked into offset but this only applies to the whole table
SELECT
myTable.name,
myTable.Id
FROM myTable
GROUP BY myTable.name HAVING COUNT(*) > 1
ORDER BY myTable.name ASC, myTable.Id ASC
What I'm getting:
NAME ID
A 1
A 2
A 3
B 1
B 2
B 3
What I want:
NAME ID
A 2
A 3
B 2
B 3
You can filter in the where clause:
select name, id
from t
where t.id > (select min(t2.id) from t t2 where t2.name = t.name);
I excluded the lowest ID from the query by doing concat and group by finding the MIN value:
DECLARE #myTable TABLE ( NAME NVARCHAR(MAX), ID INT )
INSERT INTO #myTable VALUES
('A',1),
('A',2),
('A',3),
('B',1),
('B',2),
('B',3)
SELECT * FROM #myTable
WHERE CONCAT(NAME,ID) NOT IN
(
SELECT CONCAT(NAME,MIN(ID)) FROM #myTable
GROUP BY NAME
)
GROUP BY NAME,ID
ORDER BY NAME,ID ASC
OUTPUT:
NAME ID
A 2
A 3
B 2
B 3
MY SQL--->
insert into table b (col list)
select id,
Col2 = ( select col from table B where col5 = 'true'),
Col3 = ( select col from table B where col4 = 'true')
from table a
in this i am getting error
Err] 1242 - Sub query returns more than 1 row
is there any another method to do the same functionality?
You inner queries are returning more than 1 values. This will work since I have limited the inner query result to 1 but I am not sure whether your requirements are satisfied or not.
insert into table b (col list)
select id,
Col2 = ( select col from (select col from table B where col5 = 'true' limit 0,1) as alias ),
Col3 = ( select col from (select col from table B where col4 = 'true' limit 0,1) as alias 2)
from table a
i have table like that in mysql:
from value to
1 45 2
3 20 4
2 45 1
4 20 3
I want to check values 1 to 2 and 2 to 1 has the same values .
can you give me some example not exact query?
Thanks for help.
You can do this with exists. This will return all the instances where the values are not the same:
select t.*
from table t
where not exists (select 1
from table t2
where t2.from = t.to and
t2.to = t.from and
t2.value = t.value
);
One way is to group by the value. Then you can count if the from and to columns have the right values. If the count is greater than zero for both conditions then you have met your requirement.
Hover over to see the query
select value
from your_table
group by value
having sum(from = 1 and to = 2) = 1
and sum(from = 2 and to = 1) = 1
Something like this will return a row where at least one corresponding inverse row does not have a "matching" value:
SELECT a.from, a.to, a.value, b.value
FROM mytable a
JOIN mytable b
ON b.from = a.to
AND b.to = a.from
WHERE a.from < a.to
AND NOT a.value <=> b.value
(NOTE: this query doesn't identify rows that do not have an inverse row, it only identifies rows where an inverse row exists in the table, but that inverse row has a different value.)
my DB has this structure:
ID | text | time | valid
This is my current code. I'm trying to find a way to do this as one query.
rows = select * from table where ID=x order by time desc;
n=0;
foreach rows{
if(n > 3){
update table set valid = -1 where rows[n];
}
n++
}
I'm checking how many rows exist for a given ID. Then I need to set valid=-1 for all rows where n >3;
Is there a way to do this with one query?
You can use a subquery in the WHERE clause, like this:
UPDATE table
SET valid=-1
WHERE (
SELECT COUNT(*)
FROM table tt
WHERE tt.time > table.time
AND tt.ID = table.ID
) > 3
The subquery counts the rows with the same ID and a later time. This count will be three or less for the three latest rows; the remaining ones would have a greater count, so their valid field would be updated.
Assuming that (id,time) has a UNIQUE constraint, i.e. no two rows have the same id and same time:
UPDATE
tableX AS tu
JOIN
( SELECT time
FROM tableX
WHERE id = #X -- the given ID
ORDER BY time DESC
LIMIT 1 OFFSET 2
) AS t3
ON tu.id = #X -- given ID again
AND tu.time < t3.time
SET
tu.valid = -1 ;
update table
set valid = -1
where id in (select id
from table
where id = GIVEN_ID
group by id
having count(1) >3)
Update: I really like dasblinkenlight's solution because is very neat, but I wanted to try also to do it in my way, a quite verbose one:
update Table1
set valid = -1
where (id, time) in (select id,
time
from (select id,time
from table1
where id in (select id
from table1
group by id
having count(1) >3)
-- and id = GIVEN_ID
order by time
limit 3, 10000000)
t);
Also in SQLFiddle
to do it for all ids, or only for one if you set a where in the a subquery
UPDATE TABLE
LEFT JOIN (
SELECT *
FROM (
SELECT #rn:=if(#prv=id, #rn+1, 1) AS rId,
#prv:=id AS id,
TABLE.*
FROM TABLE
JOIN ( SELECT #prv:=0, #rn:=0 ) tmp
ORDER BY id, TIMESTAMP
) a
WHERE rid > 3
) ordered ON ordered.id = TABLE.id
AND ordered.TIMESTAMP = TABLE.TIMESTAMP
AND ordered.text = TIMESTAMP.text
SET VALID = -1
WHERE rid IS NOT NULL
I have a table name T1 having only one Column name Col1 having rows –
Col1
a
b
c
And another table name T2 also having only one Column name Col1 having rows –
Col1
x
y
z
Now I want record like
Col1--Col2
a------x
b------y
c------z
I am using mysql.
Thanks in advance!!
create table T1(col1 varchar(10));
insert T1 values ('a'),('b'),('c');
create table T2(col2 varchar(10));
insert T2 values ('x'),('y'),('z');
select A.col1, B.col2 from
(select #r:=#r+1 rownum, col1 from (select #r:=0) initvar, T1) A,
(select #s:=#s+1 rownum, col2 from (select #s:=0) initvar, T2) B
where A.rownum=B.rownum
Because there is no ORDER BY clause, you are depending on luck and convention for the row numbering to be according to the order inserted. It may not always be the case.
In your example, if you want to join the tables to get row results like this:
Row 1 - A,X
Row 2 - B,Y
Row 3 - C,Z
..then you will have to add a common field that you can JOIN the two tables on.
If you want to be able to return results from both tables like this:
Row 1 - A
Row 2 - B
Row 3 - C
Row 4 - X
Row 5 - Y
Row 6 - Z
.. then you will need to use a UNION:
(SELECT Col1 FROM T1) UNION (SELECT Col1 FROM T2)