Adding a new column in SQL which calculates value from other columns - mysql

I was trying to create a new column in SQL which has calculated values from other columns in the same table.
Please see the case below
col1 col2
A 1
A 2
B 1
B 2
B 3
I need to create a new column 'col3' that finds the max of col2 grouped by col1. So the result i want is
col1 col2 col3
A 1 2
A 2 2
B 1 3
B 2 3
B 3 3
I would like to know if a query can be something along the below lines
ALTER TABLE table1 ADD col3 AS (SELECT max(col2) GROUPBY col1)

You don't need an ALTER statement and can get the extra column in your SELECT query like
select col1, col2, max(col2) as col3
from tbl1
group by col1

Related

GROUP BY clause ignoring first column value if second and third are the same

Database server is MySQL
I have an SQL query that does a select with a "GROUP BY" clause as follows:
SELECT col1, col2, col3, SUM(col4), SUM(col5) where col6 = 20 GROUP BY col1, col2, col3
All works well when col2 and col3 have different values but when col2 and col3 have the same value as follows
col1 col2 col3 col4 col5
a 1 2 1 1
b 1 2 2 2
b 1 2 3 3
c 1 2 4 4
the query result is
c 1 2 10 10
I was expecting
a 1 2 1 1
b 1 2 5 5
c 1 2 4 4
Why does the "GROUP BY" ignore the fact that the col1 values are not all the same and just displays that last one it finds?
Thanks in advance
User error - turn out I was aliasing col1 and there was a column of the same name in the table so the GROUP BY was using the column name and not the alias. The column name is question was not even part of the query.
The pitfalls of working on a system that someone else wrote.
Thanks for all your suggestions/comments

SQL Select rows where col1 or col2 equals variable

So I want to select rows from table where col1 or col2 equals to variable, but if there is already row selected where col1 equals to variable (variable X) and col2 is anything else (variable Y) then it won't select another row where col2 equals to variable X and col1 equals to that variable Y. Everything ordered by column TIME descending.
Let's say this is my table:
COL1 COL2 TIME COL4
1 2 0 A
1 2 1 B
2 1 2 C
1 3 3 D
3 1 4 E
4 2 5 F
3 4 6 G
1 2 7 H
4 1 8 I
And let's say that variable X equals to 1, then I want to have these rows:
COL1 COL2 TIME COL4
4 1 8 I
1 2 7 H
3 1 4 E
So it won't show me this row
COL1 COL2 TIME COL4
2 1 2 C
because there is already a combination where col1/col2 is 2/1 or 1/2.
Sorry if I explained it in a bad way, but I can't think of better explanation.
Thank you guys.
Making a couple of key assumptions...
SELECT a.*
FROM my_table a
JOIN
( SELECT MAX(time) time
FROM my_table
WHERE 1 IN (COL1,COL2)
GROUP
BY LEAST(col1,col2)
, GREATEST(col1,col2)
) b
ON b.time = a.time;
EDIT: I posted this answer when it was thought that OP's database was SQL Server. But as it turns out, the database is MySQL.
I think this query should do it:
select t.col1, t.col2, t.time, t.col4
from (select t.*,
row_number() over (
partition by
case when col1 < col2 then col1 else col2 end,
case when col1 < col2 then col2 else col1 end
order by time desc) as rn
from tbl t
where t.col1 = x or t.col2 = x) t
where t.rn = 1
order by t.time desc
The key part is defining the row_number partition by clause in such a way that (1, 2) is considered equivalent to (2, 1), which is what the case statements do. Once the partitioning works correctly, you just need to keep the first row of every "partition" (where t.rn = 1) to exclude duplicate rows.

how to achieve concatenation using group by

Suppose there is a table named 'a' with following data:
col1, col2
-----------
1 1
1 2
1 3
2 2
2 3
3 4
then to achieve following results:
col1, col2
--------------
1 6
2 5
3 4
i can run query like :
select col1, sum(col2) from a group by col1.
But suppose my table is:
col1, col2
---------
1 a
1 b
1 c
2 d
2 e
3 f
here col2 is of varchar type not of numeric type.
what will be the sql query to give following results???
col1, col2
------------
1 a,b,c
2 d,e
3 f
i have tried group by on col1 but how to concatenate values in col2???
the problem is that col2 is of varchar type.
In case of MySQL you can use GROUP_CONCAT like this:
SELECT
col1,
GROUP_CONCAT(col2) as col2
FROM demo
GROUP BY col1;
Here is the sqlfiddle.
In case of SQL Server you can use STUFF like this:
SELECT t1.col1,
stuff((SELECT ',' + CAST(t2.col2 as VARCHAR(10))
FROM demo t2 WHERE t1.col1 = t2.col1
FOR xml path('')),1,1,'') col2
FROM demo t1
GROUP BY t1.col1;
Here is the sqlfiddle.
You can use group_concat function in mysql
select
col1,
group_concat(col2) as col2
from table_name
group by col1
Here is a good example, I ran into a similar issue whilst coding up a schedule (working example: www.oldiesplus.com/schedule/)
Here is the link to my question with answer: https://stackoverflow.com/a/27047139

remove tuples within a column with condition

I have a table with duplicates (COL2) within the same category (defined in COL1), when I try to delete tuples within COL2, I can't find a way to do this only within the same category, instead it deletes tuples everywhere in the table.
Here is the current table T1 BEFORE removing duplicates:
COL1 COL2
A 1
A 2
A 2
A 2
B 1
B 2
B 2
B 3
Here is the current table T1 AFTER removing duplicates:
COL1 COL2
A 1
A 2
B 3
Here is what I should have in T1:
COL1 COL2
A 1
A 2
B 1
B 2
B 3
Here is the code I used to delete duplicates:
CREATE TABLE TEMP LIKE T1;
INSERT INTO TEMP SELECT * FROM T1 WHERE 1 GROUP BY COL2;
DROP TABLE T1;
ALTER TABLE TEMP RENAME T1;
Any idea how to tell mysql to delete tuples only within a category of COL1?
Use both columns in your GROUP BY clause:
INSERT INTO TEMP
SELECT *
FROM T1
GROUP BY COL1, COL2

How to fetch changed rows by comparing a table with its older version?

I have one log table and one view.
I would like to fetch the changed rows from the view by comparing it to the log table given an ID_NO.
The ID_NO is fixed between the two tables, whereas other columns can change.
In short, I would like to fetch the rows from Table1 which have one more changed columns in comparison to Table2.
for example:
TABLE 1:
ID COL1 COL2 COL3
1 A B C
2 34 56 D
3 F XY 24
TABLE 2:
ID COL1 COL2 COL3
1 A B C
2 34 56 F
3 1 XY 24
The query should return the following from TABLE2:
ID COL1 COL2 COL3
2 34 56 F
3 1 XY 24
Please advise.
Many Thanks!
SELECT *
FROM one_view vw
WHERE EXISTS
(
SELECT 1
FROM log_table t
WHERE vw.id_no = t.id_no
)
;
A note after the question was updated:
SELECT *
FROM table_2 t1
WHERE EXISTS
(
SELECT 1
FROM table_1 t2
WHERE t1.id_no = t2.id_no
AND
(
t1.col1 <> t2.col1
OR t1.col2 <> t2.col2
OR t1.col3 <> t2.col3
)
)
;
you could add a trigger to the changing table that inserts the id in a second table that is used to identify the changed rows from the changing table. Just comparing the values between tables might work but requires a lot of work. Getting the id's of the changed rows might be easier.
Just in case you also want to have the old values, add the changed colums and values to the logging table.