MariaDB get counted values grouped by datetime for all possible dates - sql

1.48 table which looks like this:
CREATE TABLE `history` (
`TIMESTAMP` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`DEVICE` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_bin',
`TYPE` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_bin',
`EVENT` VARCHAR(512) NULL DEFAULT NULL COLLATE 'utf8_bin',
`READING` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_bin',
`VALUE` VARCHAR(128) NULL DEFAULT NULL COLLATE 'utf8_bin',
`UNIT` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8_bin'
)
COLLATE='utf8_bin'
ENGINE=InnoDB
;
and some data which looks like this (only a small example of the available data)
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-04 21:16:06', 'DL_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-04 22:31:09', 'CD_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-04 23:24:58', 'AB_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-05 00:25:58', 'XY_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-05 01:27:58', 'XY_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-05 02:27:58', 'DL_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-05 02:29:02', 'DL_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
I want to have the amount of events grouped by date and hour for a dedicated device which works nice like this:
SELECT
DATE_FORMAT(TIMESTAMP,"%Y-%m-%d %H") AS ftimestamp,
COUNT(TIMESTAMP) AS amount
FROM
history
WHERE
DEVICE = 'DL_Motion'
AND READING = 'state'
AND VALUE = 'motion'
GROUP BY
YEAR(TIMESTAMP),MONTH(TIMESTAMP),DAY(TIMESTAMP),HOUR(TIMESTAMP);
and comes to the result:
ftimestamp
amount
2023-01-04 21
1
2023-01-05 02
2
For visualization purpose it would be great if I could get such a result:
ftimestamp
amount
2023-01-04 21
1
2023-01-04 22
0
2023-01-04 23
0
2023-01-04 00
0
2023-01-04 01
0
2023-01-05 02
2
So all possible dates and hours where no data available shall have a zero.
There are enough data in the table to generate the list of all possible dates and hours with the following select:
SELECT
DATE_FORMAT(TIMESTAMP,"%Y-%m-%d %H") AS ftimestamp
FROM
history
GROUP BY
YEAR(TIMESTAMP),MONTH(TIMESTAMP),DAY(TIMESTAMP),HOUR(TIMESTAMP);
I do not know how to combine this two request to come to the result I need.

If you have all dates available in the table, you can use conditional aggregation:
select date_format(timestamp, '%Y-%m-%d %H') as timestamp_hr,
sum(device = 'DL_Motion' and reading = 'state' and value = 'motion') as amount
from history
group by date_format(timestamp, '%Y-%m-%d %H')
The logic is to scan the whole table so we do get all available dates, and then to count the relevant rows only, using the conditional sum().
Note that I aligned the date expression in the select and group by clauses, which makes more sense in standard SQL.

Related

Snowflake OR condition inside the ON clause is only working on one field even when the other exists

I am getting data from dynamic source, where 2 fields could exists within the data or only one of them.
Those fields are FACILITY_ID and BLOCK.
Some data has only BLOCK, and some has both, and I need to do a MERGE INTO to add what is available into HUB_LOCATION.
Some data will come like that:
And some would have only BLOCK and some would have both:
I tried this query:
MERGE INTO HUB_LOCATION HL
USING (SELECT md5(CONCAT_WS('', 'FACILITY', OBJECT_CONSTRUCT(*):FACILITY_ID)) AS FACILITY_HKEY,
md5(CONCAT_WS('', 'BLOCK', OBJECT_CONSTRUCT(*):BLOCK)) AS BLOCK_HKEY, OBJECT_CONSTRUCT(*):FACILITY_ID AS FACILITY_ID, OBJECT_CONSTRUCT(*):BLOCK AS BLOCK FROM TEMP_TABLE ) ST
ON (md5(CONCAT_WS('', 'FACILITY', ST.FACILITY_ID)) = HL.LOCATION_HKEY OR md5(CONCAT_WS('', 'BLOCK', ST.BLOCK)) = HL.LOCATION_HKEY )
WHEN NOT MATCHED AND ST.FACILITY_HKEY IS NOT NULL THEN
INSERT (LOCATION_HKEY, LOAD_DT, RECORD_SRC, LOCATION_VALUE, LOCATION_TYPE)
VALUES (md5(CONCAT_WS('', 'FACILITY', ST.FACILITY_ID)), CURRENT_TIMESTAMP(), 'ONA', ST.FACILITY_ID, 'FACILITY')
WHEN NOT MATCHED AND ST.BLOCK IS NOT NULL THEN
INSERT (LOCATION_HKEY, LOAD_DT, RECORD_SRC, LOCATION_VALUE, LOCATION_TYPE)
VALUES (md5(CONCAT_WS('', 'BLOCK', ST.BLOCK)), CURRENT_TIMESTAMP(), 'ONA', ST.BLOCK, 'BLOCK');
This merge statement will only work when there is only one of both fields.
Within the ON clause I tried to change OR to AND but the script ran non stop.
I reproduced what it appears you're doing and the merge is working. The issue is the test for the first table and second table are using the same values that get matched. That inserts 0 rows from the when not matched clause. If you make a trivial change to the values, the merge works. If you need to update them if matched, you can add a clause for that. Here's all I did with the change to the second table to make the changes not match:
create or replace table HUB_LOCATION(LOCATION_HKEY string, LOAD_DT date, RECORD_SRC string, LOCATION_VALUE string, LOCATION_TYPE string);
create or replace table TEMP_TABLE(id int, facility_id string, "name" string);
insert into TEMP_TABLE (id, facility_id, "name") values (1, '1A', 'xyz'), (2, '1A', 'abc'), (3, '2C', 'ac');
create or replace table TEMP_TABLE(id int, facility_id string, "name" string, block string);
insert into TEMP_TABLE (id, facility_id, "name", block) values (1, '1Ax', 'xyz', 'B1'), (2, '1Ay', 'abc', 'B2'), (3, '2Cz', 'ac', 'B3');
MERGE INTO HUB_LOCATION HL
USING (SELECT md5(CONCAT_WS('', 'FACILITY', OBJECT_CONSTRUCT(*):FACILITY_ID)) AS FACILITY_HKEY,
md5(CONCAT_WS('', 'BLOCK', OBJECT_CONSTRUCT(*):BLOCK)) AS BLOCK_HKEY, OBJECT_CONSTRUCT(*):FACILITY_ID AS FACILITY_ID, OBJECT_CONSTRUCT(*):BLOCK AS BLOCK FROM TEMP_TABLE ) ST
ON (md5(CONCAT_WS('', 'FACILITY', ST.FACILITY_ID)) = HL.LOCATION_HKEY OR md5(CONCAT_WS('', 'BLOCK', ST.BLOCK)) = HL.LOCATION_HKEY )
WHEN NOT MATCHED AND ST.FACILITY_HKEY IS NOT NULL THEN
INSERT (LOCATION_HKEY, LOAD_DT, RECORD_SRC, LOCATION_VALUE, LOCATION_TYPE)
VALUES (md5(CONCAT_WS('', 'FACILITY', ST.FACILITY_ID)), CURRENT_TIMESTAMP(), 'ONA', ST.FACILITY_ID, 'FACILITY')
WHEN NOT MATCHED AND ST.BLOCK IS NOT NULL THEN
INSERT (LOCATION_HKEY, LOAD_DT, RECORD_SRC, LOCATION_VALUE, LOCATION_TYPE)
VALUES (md5(CONCAT_WS('', 'BLOCK', ST.BLOCK)), CURRENT_TIMESTAMP(), 'ONA', ST.BLOCK, 'BLOCK');
select * from HUB_LOCATION;

DB2 NOT ATOMIC WAS Expected , how can we fix this?

I m not sure , why I am getting the below error, while executing the below SQL in my SQL Editor for DB2 (DB2 for z/OS)
DECLARE GLOBAL TEMPORARY TABLE SESSION.VTI_GUI_TMP (
ENCRP_PRC_RL_ID INTEGER NOT NULL,
PROC_SYS_CD VARCHAR(10) NOT NULL,
VER_KEY_SET_CD VARCHAR(10) NOT NULL,
TRNSLT_TP_CD VARCHAR(10) NOT NULL,
SET_INDEX_NUM VARCHAR(10) NOT NULL,
SET_MDK_DKI_NUM VARCHAR(10) NOT NULL,
PACKET_NUM INTEGER NOT NULL ) ON COMMIT PRESERVE ROWS;
INSERT INTO SESSION.VTI_GUI_TMP (
ENCRP_PRC_RL_ID, PROC_SYS_CD, VER_KEY_SET_CD, TRNSLT_TP_CD,
SET_INDEX_NUM, SET_MDK_DKI_NUM, PACKET_NUM
)
VALUES (500159, 'DB', 'MDK', '0', '1', '001', 766473)
UNION ALL
(500151, 'DB', 'MDK', '0', '2', '002', 766473);
select * from SESSION.VTI_GUI_TMP;
DROP TABLE SESSION.VTI_GUI_TMP;
I am getting the below error , while executing the above the SQL
ILLEGAL USE OF KEYWORD UNION. TOKEN FOR NOT ATOMIC WAS EXPECTED. SQLCODE=-199, SQLSTATE=42601, DRIVER=3.63.75 SQL Code: -199, SQL State: 42601
Error occurred in:
INSERT INTO SESSION.VTI_GUI_TMP (ENCRP_PRC_RL_ID, PROC_SYS_CD, VER_KEY_SET_CD, TRNSLT_TP_CD, SET_INDEX_NUM, SET_MDK_DKI_NUM, PACKET_NUM) VALUES(500159, 'DB', 'MDK', '0', '1', '001', 766473) UNION ALL(500151, 'DB', 'MDK', '0', '2', '002', 766473)
How can we fix the above error ? I dont want to use the SELECT statement along with UNION ALL to fix. Is there any way to make this work.
I am using the below DB2 version
SELECT GETVARIABLE('SYSIBM.VERSION') FROM SYSIBM.SYSDUMMY1
-----------
DSN11015
What am I doing wrong?
Can't you use two separate INSERT statements? For example:
DECLARE GLOBAL TEMPORARY TABLE SESSION.VTI_GUI_TMP (
ENCRP_PRC_RL_ID INTEGER NOT NULL,
PROC_SYS_CD VARCHAR(10) NOT NULL,
VER_KEY_SET_CD VARCHAR(10) NOT NULL,
TRNSLT_TP_CD VARCHAR(10) NOT NULL,
SET_INDEX_NUM VARCHAR(10) NOT NULL,
SET_MDK_DKI_NUM VARCHAR(10) NOT NULL,
PACKET_NUM INTEGER NOT NULL
) ON COMMIT PRESERVE ROWS;
INSERT INTO SESSION.VTI_GUI_TMP (
ENCRP_PRC_RL_ID, PROC_SYS_CD, VER_KEY_SET_CD, TRNSLT_TP_CD,
SET_INDEX_NUM, SET_MDK_DKI_NUM, PACKET_NUM
) VALUES (500159, 'DB', 'MDK', '0', '1', '001', 766473)
INSERT INTO SESSION.VTI_GUI_TMP (
ENCRP_PRC_RL_ID, PROC_SYS_CD, VER_KEY_SET_CD, TRNSLT_TP_CD,
SET_INDEX_NUM, SET_MDK_DKI_NUM, PACKET_NUM
) VALUES (500151, 'DB', 'MDK', '0', '2', '002', 766473);
Or maybe:
INSERT INTO SESSION.VTI_GUI_TMP (
ENCRP_PRC_RL_ID, PROC_SYS_CD, VER_KEY_SET_CD, TRNSLT_TP_CD,
SET_INDEX_NUM, SET_MDK_DKI_NUM, PACKET_NUM)
SELECT 500159, 'DB', 'MDK', '0', '1', '001', 766473 FROM sysibm.sysdummy1
UNION ALL
SELECT 500151, 'DB', 'MDK', '0', '2', '002', 766473 FROM sysibm.sysdummy1
Since the syntax was not accurate, Db2 attempted to provide guidance on what might be expected. In the example SQL, Db2 thought you might be wanting to use a multiple-row-insert where NOT ATOMIC is expected. For the INSERT statement, the VALUES clause supports an expression, DEFAULT, and NULL (https://www.ibm.com/support/knowledgecenter/SSEPEK_12.0.0/sqlref/src/tpc/db2z_sql_insert.html). An INSERT with VALUES using UNION ALL is currently not supported. The two examples provided by #The Impaler appear to be valid syntax: 1) INSERT with VALUES using valid expressions and 2) INSERT with fullselect.

How to assign column data into column name

Please find below sql query
create table test_bin (date1 varchar2(10), desc varchar2(10), values number(10));
insert into test_bin values ('10DEC2015', 'ABC', 10);
insert into test_bin values ('10DEC2015', 'CDE', 20);
insert into test_bin values ('10DEC2015', 'XYZ', 35);
insert into test_bin values ('12DEC2015', 'ABC', 10);
insert into test_bin values ('12DEC2015', 'CDE', 45);
insert into test_bin values ('12DEC2015', 'XYZ', 98);
insert into test_bin values ('13DEC2015', 'ABC', 76);
insert into test_bin values ('13DEC2015', 'CDE', 86);
insert into test_bin values ('13DEC2015', 'XYZ', 63);
commit;
question:-
I am expecting following output, I tried my level best i can't able to get proper query
DESC 10DEC2015 12DEC2015 13DEC2015
ABC 10 NULL NULL
CDE 20 NULL NULL
XYZ 35 NULL NULL
ABC NULL 10 NULL
CDE NULL 45 NULL
XYZ NULL 98 NULL
ABC NULL NULL 76
CDE NULL NULL 86
XYZ NULL NULL 63
It's just one way :
select desc,
SUM(case when date1='10DEC2015' then values end) as "10DEC2015",
sum(case when date1='12DEC2015' then values end) as "12DEC2015",
sum(case when date1='13DEC2015' then values end) as "13DEC2015"
from test_bin
group by date1, desc;
It supposes that you already know all existing values for date1, except if you create dynamically your request.
PS : be careful about using SQL keyword as column name
PS1 : http://www.sqlfiddle.com/#!9/20068f/5, it's in MySQL because 10g was not available and Oracle is far away from me AND column name has been changed to avoid conflict with SQL keywords

How to copy in field if query returns it blank?

I am writing query
from two different tables.
Table A and Table B
Here is Query.
select
A.OUT_NUM,
A.TIMESTAMP,
A.LAST_name,
A.event_type,
A.comments,
B.name
from TABLEA A
left outer join TABLEB B ON A.feed_id = B.id
where A.OUT_NUM = '12345'
and A.event_type In ('cause','status')
B.NAME is not null when event_type = xyz else it will be null
I only want to see when event_type in ('CAUSE','STATUS') but also want to see name field but not empty.
second table is what I am trying to achieve.
Thanks
Making some assumptions about your data as in comments, particularly about how to match and pick a substitute name value; and with some dummy data that I think matches yours:
create table tablea(out_num number,
equip_name varchar2(5),
event_type varchar2(10),
comments varchar2(10),
timestamp date, feed_id number);
create table tableb(id number, name varchar2(10));
alter session set nls_date_format = 'MM/DD/YYYY HH24:MI';
insert into tablea values (12345, null, 'abcd', null, to_date('02/11/2013 11:12'), 1);
insert into tablea values (12345, null, 'abcd', null, to_date('02/11/2013 11:11'), 1);
insert into tablea values (12345, null, 'abcd', null, to_date('02/11/2013 11:06'), 1);
insert into tablea values (12345, null, 'abcd', null, to_date('02/11/2013 11:06'), 1);
insert into tablea values (12345, null, 'SUB', null, to_date('02/11/2013 11:11'), 2);
insert into tablea values (12345, null, 'SUB', null, to_date('02/11/2013 11:12'), 2);
insert into tablea values (12345, null, 'XYZ', null, to_date('02/11/2013 11:13'), 3);
insert into tablea values (12345, null, 'XYZ', null, to_date('02/11/2013 11:13'), 3);
insert into tablea values (12345, null, 'XYZ', null, to_date('02/11/2013 11:13'), 3);
insert into tablea values (12345, null, 'XYZ', null, to_date('02/11/2013 11:13'), 3);
insert into tablea values (12345, null, 'XYZ', null, to_date('02/11/2013 11:13'), 3);
insert into tablea values (12345, null, 'XYZ', null, to_date('02/11/2013 11:03'), 3);
insert into tablea values (12345, null, 'CAUSE', 'APPLE', to_date('02/11/2013 11:13'), 4);
insert into tablea values (12345, null, 'CAUSE', 'APPLE', to_date('02/11/2013 11:13'), 4);
insert into tablea values (12345, null, 'CAUSE', 'APPLE', to_date('02/11/2013 11:13'), 4);
insert into tablea values (12345, null, 'STATUS', 'BOOKS', to_date('02/11/2013 11:13'), 5);
insert into tablea values (12345, null, 'STATUS', 'BOOKS', to_date('02/11/2013 11:13'), 5);
insert into tablea values (12345, null, 'STATUS', 'BOOKS', to_date('02/11/2013 11:03'), 5);
insert into tableb values(3, 'LION');
This gets your result:
select * from (
select a.out_num,
a.timestamp,
a.equip_name,
a.event_type,
a.comments,
coalesce(b.name,
first_value(b.name)
over (partition by a.out_num
order by b.name nulls last)) as name
from tablea a
left outer join tableb b on a.feed_id = b.id
where a.out_num = '12345'
and a.event_type in ('CAUSE', 'STATUS', 'XYZ')
)
where event_type in ('CAUSE', 'STATUS');
OUT_NUM TIMESTAMP EQUIP_NAME EVENT_TYPE COMMENTS NAME
---------- ------------------ ---------- ---------- ---------- ----------
12345 02/11/2013 11:03 STATUS BOOKS LION
12345 02/11/2013 11:13 STATUS BOOKS LION
12345 02/11/2013 11:13 STATUS BOOKS LION
12345 02/11/2013 11:13 CAUSE APPLE LION
12345 02/11/2013 11:13 CAUSE APPLE LION
12345 02/11/2013 11:13 CAUSE APPLE LION
The inner query includes XYZ and uses the analytic first_value() function to pick a name if the directly matched value is null - the coalesce may not be necessary if there really will never be a direct match. (You might also need to adjust the partition by or order by clauses if the assumptions are wrong). The outer query just strips out the XYZ records since you don't want those.
If you want to get a name value from any matching record then just remove the filter in the inner query.
But now you're perhaps more likely to have more than one non-null record; this will give you one that matches a.feed_id if it exists, or the 'first' one (alphabetically, ish) for that out_num if it doesn't. You could order by b.id instead, or any other column in tableb; ordering by anything in tablea would need a different solution. If you'll only have one possible match anyway then it doesn't really matter and you can leave out the order by, though it's better to have it anyway.
If I add some more data for a different out_num:
insert into tablea values (12346, null, 'abcd', null, to_date('02/11/2013 11:11'), 1);
insert into tablea values (12346, null, 'SUB', null, to_date('02/11/2013 11:12'), 2);
insert into tablea values (12346, null, 'XYZ', null, to_date('02/11/2013 11:13'), 6);
insert into tablea values (12346, null, 'CAUSE', 'APPLE', to_date('02/11/2013 11:14'), 4);
insert into tablea values (12346, null, 'STATUS', 'BOOKS', to_date('02/11/2013 11:15'), 5);
insert into tableb values(1, 'TIGER');
...then this - which just has the filter dropped, and I've left out the coalesce this time - gives the same answer for 12345, and this for 12346:
select * from (
select a.out_num,
a.timestamp,
a.equip_name,
a.event_type,
a.comments,
first_value(b.name)
over (partition by a.out_num
order by b.name nulls last) as name
from tablea a
left outer join tableb b on a.feed_id = b.id
)
where out_num = '12346'
and event_type in ('CAUSE', 'STATUS');
OUT_NUM TIMESTAMP EQUIP_NAME EVENT_TYPE COMMENTS NAME
---------- ------------------ ---------- ---------- ---------- ----------
12346 02/11/2013 11:14 CAUSE APPLE TIGER
12346 02/11/2013 11:15 STATUS BOOKS TIGER
... where TIGER is linked to abcd, not XYZ.
Use NVL() and LAG() functions.
General example using my sample data. This query fills out blank rows with data - see first_exam and last_exam columns:
SELECT id, name, proc_date, proc_type, first_exam_date
, NVL(prev_exam_date, LAG(prev_exam_date) OVER (ORDER BY name, proc_date)) last_exam_date
FROM
(
SELECT id, name, proc_date, proc_type, first_exam_date
, NVL(first_exam_date, LAG(first_exam_date) OVER (ORDER BY name, proc_date) ) prev_exam_date
FROM
(
SELECT id
, name
, proc_date
, proc_type
, (SELECT MIN(proc_date) OVER (PARTITION BY name, proc_date)
FROM stack_test WHERE proc_type LIKE 'Exam%' AND a.id = id
) first_exam_date
FROM stack_test a
));
ID NAME PROC_DATE PROC_TYPE FIRST_EXAM_DATE LAST_EXAM_DATE
--------------------------------------------------------------------------
1 George 1/1/2013 ExamA 1/1/2013 1/1/2013
2 George 1/3/2013 TreatmentA 1/1/2013
3 George 1/5/2013 TreatmentB 1/1/2013
4 George 2/1/2013 ExamB 2/1/2013 2/1/2013
5 George 2/5/2013 TreatmentA 2/1/2013

Best way to write this query

I have two MySql tables as shown below with the data shown:
CREATE TABLE `A` (
`id` int(12) NOT NULL AUTO_INCREMENT,
`status` varchar(50) DEFAULT NULL,
`another_field` varchar(50) DEFAULT NULL
)
INSERT INTO `A` VALUES ('1', null, 'a');
INSERT INTO `A` VALUES ('2', null, 'b');
INSERT INTO `A` VALUES ('3', null, 'c');
CREATE TABLE `B` (
`id` int(12) NOT NULL AUTO_INCREMENT,
`status` varchar(50) DEFAULT NULL,
`tableA_id` int(12) DEFAULT NULL,
PRIMARY KEY (`id`)
)
INSERT INTO `B` VALUES ('1', 'aa', '1');
INSERT INTO `B` VALUES ('2', 'aa', '1');
INSERT INTO `B` VALUES ('3', 'aa', '2');
INSERT INTO `B` VALUES ('4', 'aa', '3');
INSERT INTO `B` VALUES ('5', 'bb', '3');
I want to know if it is possible to update A.status if all B.status are the same when A.id = B.tableA_id using a single query?
This is what I want my table A to look like:
('1', 'aa', 'a') - Status is updated to 'aa' as B.id 1 & 2 have the same status and same B.tableA_id value.
('2', 'aa', 'b') - Status is updated to 'aa' as B.id 3 has the same status.
('3', null, 'c') - This is not updated because B.id 4 & 5 have different status and the same table2.table1_id value.
Thanks
UPDATE A
SET status = COALESCE((
SELECT MAX(B.status)
FROM B
WHERE B.tableA_id = A.id
HAVING MAX(B.status) = MIN(B.status)
), A.status)
(Note: I added a correction, you need the COALESCE(..., A.status) or otherwise the status will be set to NULL in case there were multiple statuses in B
Not sure about MySql but in MSSQL you could write something like:
UPDATE A SET A.Status = 'aa'
FROM A INNER JOIN B on A.id = B.tableA_id
WHERE b.status = 'aa'
It should be similar in MySQL, but I'm not if the language supports joins on update. But still I hope it helps.
UPDATE a SET status =
(
SELECT status FROM b WHERE tableA_id = a.id LIMIT 0,1
)
WHERE id IN
(
SELECT tableA_id FROM b
GROUP BY tableA_id
HAVING COUNT(DISTINCT status) = 1
)
Update: Roland was right; I have updated the query and it now yields the correct results.
CREATE TABLE `A` (
`id` int(12) NOT NULL AUTO_INCREMENT,
`status` varchar(50) DEFAULT NULL,
`another_field` varchar(50) DEFAULT NULL
)
INSERT INTO `A` VALUES ('1', null, 'a');
INSERT INTO `A` VALUES ('2', null, 'b');
INSERT INTO `A` VALUES ('3', null, 'c');
CREATE TABLE `B` (
`id` int(12) NOT NULL AUTO_INCREMENT,
`status` varchar(50) DEFAULT NULL,
`tableA_id` int(12) DEFAULT NULL,
PRIMARY KEY (`id`)
)
INSERT INTO `B` VALUES ('1', 'aa', '1');
INSERT INTO `B` VALUES ('2', 'aa', '1');
INSERT INTO `B` VALUES ('3', 'aa', '2');
INSERT INTO `B` VALUES ('4', 'aa', '3');
INSERT INTO `B` VALUES ('5', 'bb', '3');