Combining 2 rows in table - mysql

I have the following data:
-------table_a-------
| id | data | value |
| 1 | 5 | 1 |
| 2 | 3 | 3 |
My desired output is to merge row 2 with row 1 so that where id = 1, data remains to =5 but the values are added, so 1+3.
-------table_a-------
| id | data | value |
| 1 | 5 | 4 |
This is as far as I got with the queries but the first isn't seeming to work. Also this is not for retrieving the data, this is for manipulating the data in the database.
Current queries (1st not working):
UPDATE table_a SET value = value + (SELECT a.value FROM table_a a WHERE a.id = 2) WHERE id = 1;
DELETE FROM table_a WHERE id = 2;

If this is the logic that you want:
UPDATE table_a
SET value = value + (SELECT a.value FROM table_a a WHERE a.id = 2)
WHERE id = 1;
DELETE FROM table_a WHERE id = 2;
The update is not going to work because you cannot reference the table being updated in the rest of the query. You can use a hack for the update and do:
UPDATE table_a
SET value = value + (SELECT value FROM (SELECT a.value FROM table_a a WHERE a.id = 2) )
WHERE id = 1;
The double select fixes this problem. The more correct method is to use join:
UPDATE table_a a CROSS JOIN
(SELECT a.value FROM table_a a WHERE a.id = 2) as a2
SET a.value = a.value + a2.value
WHERE id = 1;

Here is one way on how you can make an accumulative column by joining the table with itself.
I'm assuming the Id column is an identity column,
Hope this helps.
CREATE TABLE [dbo].[TestTable](
[id] [int] NULL,
[data] [int] NULL,
[value] [int] NULL
) ON [PRIMARY]
INSERT INTO [dbo].[TestTable]
([id]
,[data]
,[value])
VALUES
(1,5,1),
(2,3,3),
(3,4,4)
SELECT a.id , a.data , a.value + b.value as Sum
FROM [TestTable] a
left join [TestTable] b
on a.id + 1 = b.id

This will work, please check.
UPDATE table_a,
(SELECT value as val FROM table_a where id = 2) AS t2
SET table_a.value = table_a.value+t2.val
where table_a.id = 1;
DELETE from table_a where id = 2;

Related

MySQL - Select results with specified ID or with null

I have one table:
| ID | ADV_ID | USER_ID |
| 1 | 22 | NULL |
| 2 | 22 | 3 |
| 5 | 44 | NULL |
and now, I want to select row where adv_id = 22 and user_id = 3. If that row doesn't exist, I want to get row where adv_id = 22 and user_id is null.
I tried in that way:
SELECT * FROM `table` WHERE adv_id = 22 AND (user_id = 3 OR user_id is null)
but this query return two rows - with user_id = NULL and with user_id = 3. I want to get one row - with user_id = 3 or (if not exist), with user_id = NULL.
How I can do it in one query?
Thanks.
Use conditional aggregation:
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT
ADV_ID,
CASE WHEN COUNT(CASE WHEN USER_ID = 3 THEN 1 END) > 0 THEN 3 END USER_ID
FROM yourTable
) t2
ON t1.ADV_ID = t2.ADV_ID AND
((t1.USER_ID IS NULL AND t2.USER_ID IS NULL) OR (t1.USER_ID = t2.USER_ID))
WHERE
t1.ADV_ID = 22;
Demo
For an explanation, the subquery I have aliased as t2 aggregates over the ADV_ID, and outputs the value 3 if that value occurs in one or more records, otherwise it outputs NULL. Then, we join this subquery back to your original table on the condition that both USER_ID values are NULL, or, if not, that the two USER_ID values match.
You may modify the demo to see that it generates the output you want for other inputs.
SELECT *
FROM test
WHERE ADV_ID IS NOT NULL AND USER_ID IS NOT NULL
UNION ALL
SELECT *
FROM test
WHERE USER_ID IS NULL AND NOT EXISTS (
SELECT 1
FROM test
WHERE ADV_ID IS NOT NULL AND USER_ID IS NOT NULL
)
Select all rows with the first condition: ADV_ID IS NOT NULL AND USER_ID IS NOT NULL
and then UNION ALL with the same table if the first condition is NOT EXISTS.
So we only get results if the first condition is not returned any rows.
The MySQL UNION ALL operator is used to combine the result sets of 2 or more SELECT statements.
try like that:
SELECT * FROM `table` t1 WHERE (t1.adv_id = 44)
AND ((t1.user_id = 3) OR
(NOT EXISTS (select * from `table` t2 where t2.adv_id=t1.adv_id and t2.user_id = 3) AND t1.user_id is null ))
DEMO

delete rows in mysql

If I have a table:
id1 id2 count
A A 1
A B 2
A C 1
B A 3
B B 1
B C 2
C A 3
C B 2
C C 1
What I want after deleting:
id1 id2 count
A A 1
A B 2
A C 1
B B 1
B C 2
C C 1
which means if I have A(id1) --> B(id2) then delete B(id1) --> A(id2). same as B(id1) --> C(id2) then delete the row C(id1) --> B(id2)
Thank you for ur help!
In this case we analyze Target.id1 > Target.id2 mean case like (B, A, ??) where B > A
this also ignore cases like (A, A, ??)
Then use self left join to try find another row with (A, B, ??)
If we found a match then Source.id1 IS NOT NULL and we delete
SQL Fiddle Demo
DELETE Target
FROM Table1 Target
LEFT JOIN Table1 Source
ON Target.`id1` = Source.`id2`
AND Target.`id2` = Source.`id1`
AND Target.`id1` > Target.`id2`
WHERE Source.`id1` IS NOT NULL;
OUTPUT
| id1 | id2 | count |
|-----|-----|-------|
| A | A | 1 |
| A | B | 2 |
| A | C | 1 |
| B | B | 1 |
| B | C | 2 |
| C | C | 1 |
Should be something like:
DELETE FROM 'myTable'
WHERE STRCMP(id1, id2) > 0;
STRCMP function can compare the strings and return an int. From there it should be easy - something very similar to the above. If you have further trouble let me know.
It looks like what you are saying is...
If there is a (id1,id2) tuple in the table with values e.g. (a,b), and there is another tuple (b,a) that consists of the the same values, but swapped in the columns, you want to remove one of those tuples. It looks like the one you want to remove is the one that has the "greater" value in the first column.
First, identify the "duplicate" tuples.
For now, we'll ignore the tuples where the values of id1 and id2 are the same, e.g. (a,a).
SELECT s.id1
, s.id2
FROM mytable s
WHERE s.id1 > s.id2
AND EXISTS ( SELECT 1
FROM mytable r
WHERE r.id1 = s.id2
AND r.id2 = s.id1
)
ORDER BY s.id1, s.id2
If that returns the set of rows you want to remove, we can convert that into a DELETE. To do that, we need to change that query into an inline view,
We can re-write that to be like this, verify we get equivalent results.
SELECT o.id1, o.id2
FROM ( SELECT q.id1, q.id2
FROM ( SELECT s.id1, s.id2
FROM mytable s
WHERE s.id1 > s.id2
AND EXISTS ( SELECT 1
FROM mytable r
WHERE r.id1 = s.id2
AND r.id2 = s.id1
)
) q
GROUP BY q.id1, q.id2
) p
JOIN mytable o
ON o.id1 = p.id1
AND o.id2 = p.id2
ORDER BY o.id1, o.id2
Then we can convert that to a DELETE statement, replacing SELECT o.id1, o.id2 WITH DELETE o.* and removing the ORDER BY...
DELETE o.*
FROM ( SELECT q.id1, q.id2
FROM ( SELECT s.id1, s.id2
FROM mytable s
WHERE s.id1 > s.id2
AND EXISTS ( SELECT 1
FROM mytable r
WHERE r.id1 = s.id2
AND r.id2 = s.id1
)
) q
GROUP BY q.id1, q.id2
) p
JOIN mytable o
ON o.id1 = p.id1
AND o.id2 = p.id2

mysql query select from one table such that its column's values are not present in the same column's values in another table

I have two mysql tables: A, and B.
A has columns id, alpha, blabla, moreblabla, with primary key id.
B has columns id, alpha, beta, somemoreblabla, with primary key (id, alpha)
I need to select all those A.id's, for which its A.alpha is not present in any of the B.alpha's respective to every B.id = A.id
How do I do it?
Your question is not entirely clear. Do you want all A.alpha's that are not in any B.alpha? In that case a simple query like this is enough:
Select A.id from A where A.alpha NOT IN (Select B.alpha from B);
If you want to select all ID's from A that have a counterpart (an equal ID) in B but where the alpha between A and B are different it is a bit more work:
SELECT A.id FROM A
INNER JOIN B on A.id = B.id
WHERE A.alpha != B.alpha
Consider the following structure:
CREATE TABLE `A` (
`id` int(11) NOT NULL,
`alpha` varchar(255) NOT NULL
);
CREATE TABLE `B` (
`id` int(11) NOT NULL,
`alpha` varchar(255) NOT NULL
);
With inserts:
insert into A set id = 1, alpha = 'a';
insert into A set id = 2, alpha = 'b';
insert into B set id = 1, alpha = 'a';
insert into B set id = 2, alpha = 'a';
If you run the query with the join your result will be:
+----+
| id |
+----+
| 2 |
+----+
This is since ID 2 in A has a different alpha than ID 2 in B.
EDIT:
It just occurred to me that you might even mean that every A.id can occur in B multiple times. If that is what can happen you need a different approach again. Lets assume the same insert as before with an addition:
insert into A set id = 1, alpha = 'a';
insert into A set id = 2, alpha = 'b';
insert into B set id = 1, alpha = 'a';
insert into B set id = 2, alpha = 'a';
insert into B set id = 2, alpha = 'b'; <- important since there is now a 2nd 2 in B that should ensure that the record with ID 2 from A should not be returned.
insert into A set id = 3, alpha = 'c';
insert into B set id = 3, alpha = 'x'; <-- only ID 3 should now be returned due to the situation above
Our tables now look like so:
A
+----+-------+
| id | alpha |
+----+-------+
| 1 | a |
| 2 | b |
| 3 | c |
+----+-------+
B
+----+-------+
| id | alpha |
+----+-------+
| 1 | a |
| 2 | a |
| 2 | b |
| 3 | x |
+----+-------+
If this is your case the following query will do the trick:
select A.id
FROM A where A.alpha NOT IN (
select B.alpha FROM B where B.id = A.id
);
SELECT A.id
FROM
A
LEFT OUTER JOIN B ON A.id = B.id AND B.alpha = A.alpha
where B.alpha IS NULL
Here is SQL Fiddle
This will be the fastest query,better than The marked Answer in terms of query optimization.
EXPLAIN SELECT A.id
FROM
A
LEFT OUTER JOIN B ON A.id = B.id AND B.alpha = A.alpha
where B.alpha IS NULL
Here is the output :
EXPLAIN select A.id
FROM A where A.alpha NOT IN (
select B.alpha FROM B where B.id = A.id
)
Here is the EXPLAIN of Marked answer.
You can see the DIFFERENCE.
SIMPLE VS PRIMARY
SIMPLE VS DEPENDENT SUBQUERY
Hope this helps.
Use MySQL NOT IN
Try this query :-
select id from a where a.id NOT IN (select id from b)
Select A.id from table_A where A.alpha NOT IN (Select B.alpha from table_B);
The Sub-query will return a table with all the records of B.alpha from table_B.
And say it returns 1 to 5 records as result.
And say your table table_A has 1 to 10 records in A.alpha
Now your parent query will check for records in table table_A for field A.alpha which do not belongs to B.alpha (using NOT IN)
Hence the expected result is 6 to 10 as result.

PHP single query Multiple UPDATE effecting AUTO_INCREMENT id instead of order_id

Here is my super-simple table layout...
id | order
1 | 1
2 | 2
I've been trying to update the order for both entries with a single query however my query tests seem to keep updating the auto_increment id field.
My goal is to make id1 = order 2 and id2 = order1 in a single query. What am I doing wrong with my query?
UPDATE forms
SET order = CASE id
WHEN 1 THEN 2
WHEN 2 THEN 1
END
WHERE id IN (1,2);
How about doing JOIN?
UPDATE Tablename AS a
INNER JOIN Tablename AS b
ON a.id = 1 AND b.id = 2
SET a.order = b.order,
b.order = a.order
SQLFiddle Demo

Left join on the same table

i dont remember how to join a table to itself.. my table is:
| id | proc | value | kind |
| 1 | 1 | foo | a |
| 2 | 1 | bar | b |
| 3 | 2 | some | a |
And i need to retrieve the value col where proc is $proc and kind is both 'a' and 'b'.. well, i need to do have that (looking for proc = 1):
| v_a | v_b |
| foo | bar |
So i wrote this query:
SELECT
a.value AS v_a,
b.value AS v_b
FROM
(SELECT value FROM table WHERE proc = '1' AND kind = 'a') AS a,
(SELECT value FROM table WHERE proc = '1' AND kind = 'b') AS b
And works but only if in the table i have both rows for kind=a and kind=b.
But i need that if miss a row, i'll have a null value: if i look for proc=2 i must get:
| v_a | v_b |
| foo | NULL|
Instead, with my query i dont get anythong if the b or a row is missing.
Im working with mysql...How to do that?
Edit:
I could use the UNION clause, but this wont allow me to have a NULL value when one row is missing (kind=a or kind=b)
you have to do a full join in case proc exists for 'a' but not for 'b' or vice versa:
SELECT
a.value v_a,
b.value v_b
FROM (SELECT proc, value FROM tab WHERE kind = 'a') a LEFT JOIN
(SELECT proc, value FROM tab WHERE kind = 'b') b
ON a.proc = b.proc
WHERE a.proc = '1'
UNION
SELECT
a.value v_a,
b.value v_b
FROM (SELECT proc, value FROM tab WHERE kind = 'b') b LEFT JOIN
(SELECT proc, value FROM tab WHERE kind = 'a') a
ON a.proc = b.proc
WHERE b.proc = '1'
EDIT: 1st a gave MS SQL Server query (FULL JOIN) but apparently it's not supported by MYSQL, so I changed it to a UNION of 2 LEFT JOIN
I missed your need to retrieve NULLs. This is complicated, but it seems to work:
SELECT
a.value AS a_val,
(SELECT value FROM t b2 WHERE b2.proc = a.proc AND b2.id != a.id) AS b_val
FROM `t` a
WHERE a.kind = 'a'
UNION DISTINCT
SELECT
(SELECT value FROM t a2 WHERE a2.proc = b.proc AND a2.id != b.id) AS a_val,
b.value AS b_val
FROM `t` b
WHERE b.kind = 'b'
select * from t1 full outer join t2 on some_id = some_other_id?
SELECT
a.value AS v_a,
b.value AS v_b
FROM
(SELECT proc, value FROM table WHERE proc = '1' AND kind = 'a') AS a
LEFT OUTER JOIN
(SELECT proc, value FROM table WHERE proc = '1' AND kind = 'b') AS b
ON a.proc=b.proc