Cant add another table using select query in Impala - mysql

INSERT INTO admin_userhistroy(sno,UserDetails_ID,UserMessage,SystemMessage_ID,insdate,STATUS,UserDetails_MsgTo_ID,License_Status)
VALUES ('1',(SELECT DISTINCT id FROM admin_userdetails WHERE token = 'ABCDE1' LIMIT 1)
,'New User is Created','4',cast(NOW() as string),'Y',cast((SELECT DISTINCT ID FROM admin_userdetails WHERE UserName = 'cangoadmin' AND token ='ABCDE1' LIMIT 1)as string)
,NULL)
Above is my query I have executed the same query in Mysql but I cant execute the same in Impala, someone please help me out.
I get the following error:
Subqueries not supported in the selected list

Try insert . . . select:
INSERT INTO admin_userhistroy(sno,U serDetails_ID, UserMessage, SystemMessage_ID, insdate, STATUS, UserDetails_MsgTo_ID, License_Status)
SELECT '1', x.id, 'New User is Created', '4',
cast(NOW() as string), 'Y', y.id
FROM (SELECT id FROM admin_userdetails WHERE token = 'ABCDE1' LIMIT 1) x CROSS JOIN
(SELECT CAST(ID as string) as id FROM admin_userdetails WHERE UserName = 'cangoadmin' AND token ='ABCDE1' LIMIT 1) y;
Note that you don't need select distinct in the subqueries.

Related

Find the latest rows by filtering the status

I have a table called person_list. The data is,
Insert into person_list(person_allocation_id, person_id, created_datetime, boss_user_name, allocation_status_id) values
(111008, 1190016, '2021-01-05 11:09:25', 'Rajesh', '2'),
(111007, 1190015, '2020-12-12 09:23:31', 'Sushmita', '2'),
(111006, 1190014, '2020-12-11 10:48:26', '', '3'),
(111005, 1190014, '2020-12-10 13:46:15', 'Rangarao', '2'),
(111004, 1190014, '2020-12-10 13:36:10', '', '3');
Here person_allocation_id is the primary key.
person_id may be duplicated some times.
All of these rows are sorted by person_allocation_id (in descending order)
Now, I would like to filter the rows which are having allocation_status_id = '2' and boss_user_name should be non-empty for the person_id.
The difficulty here is that I have to exclude the row if the person_id is having allocation_status_id = '3' as their latest status (according to date).
I am unable to understand how could I compare the dates in one row with another in the previous row.
So finally I should get only 2 rows in my final result set (person_allocation_id are 111008 and 111007).
Somehow I achieved this in Oracle.
select person_id, person_allocation_id, create_datetime, boss_user_name, allocation_status_id
from (
select person_id, person_allocation_id, create_datetime, boss_user_name, allocation_status_id,
rank() over (partition by person_id order by create_datetime desc) rnk
from person_list
where allocation_status_id = '2')
where rnk = 1;
But, I need this for MySql DB. Anyone, please help?
Thanks.
SELECT t1.*
FROM person_list t1
JOIN ( SELECT MAX(t2.person_allocation_id) person_allocation_id, t2.person_id
FROM person_list t2
GROUP BY t2.person_id ) t3 USING (person_allocation_id, person_id)
WHERE t1.allocation_status_id = '2'
fiddle
Add more conditions to WHERE clause if needed (for example, AND boss_user_name != '').
You can use a correlated subquery to get the latest allocation_status_id value per person_id:
select person_allocation_id
, person_id
, created_datetime
, boss_user_name
, allocation_status_id
from (
select person_allocation_id
, person_id
, created_datetime
, boss_user_name
, allocation_status_id
, (select pl2.allocation_status_id
from person_list pl2
where pl2.person_id = pl.person_id
order by pl2.created_datetime desc
limit 1) latest_allocation_status_id
from person_list pl) t
where
allocation_status_id = '2' and latest_allocation_status_id <> '3'
and boss_user_name <> ''
The outer query is able to check the latest status and return the expected result set. The query works for MySQL 5.7
Demo here
As a side note, for MySQL 8.0 you can replace the correlated subquery with a window function:
last_value(allocation_status_id) over (partition by person_id
order by created_datetime desc)
Demo for window function

mysql query with grouping and concatenate rows into one row

I have the table in mysql with records:
I've written the sql query:
SELECT COUNT(*) AS number_of_contacts, channel_id, direction
FROM cic_case_contacts
WHERE case_id = 328678
GROUP BY channel_id, direction
and the result looks like:
I would like to obtain something like below(based on above data):
I was trying to obtaining that with sql query by using my_sql_function GROUP_CONCAT but it dosen't work:
SELECT COUNT(*) AS number_of_contacts, channel_id, GROUP_CONCAT(direction SEPARATOR ', ') AS directions
FROM cic_case_contacts
WHERE case_id = 328678 AND id IN(149196, 149195, 149194, 149193, 149192) AND `office_id` = 10
GROUP BY channel_id
ORDER BY channel_id
I would be greateful for help.
You can use GROUP_CONCAT on a sub query as follows:
SELECT channelid, GROUP_CONCAT(
CONCAT(direction, ': ', c)
ORDER BY direction
SEPARATOR ', '
) AS summary
FROM (
SELECT channelid, direction, COUNT(*) AS c
FROM t
GROUP BY channelid, direction
) x
GROUP BY channelid
Or simply use conditional aggregation:
SELECT channelid, CONCAT_WS(', ',
CONCAT('in: ', COUNT(CASE WHEN direction = 'in' THEN 1 END)),
CONCAT('out: ', COUNT(CASE WHEN direction = 'out' THEN 1 END))
) AS summary
FROM t
GROUP BY channelid
You can use Concat in MySQL
drop table if exists Demo;
CREATE TABLE Demo
(
ID INT AUTO_INCREMENT PRIMARY KEY,
channelid int,
Name VARCHAR(20)
);
INSERT INTO Demo(channelid, Name)VALUES
(1,'in'),(1,'out'),(1,'in'),(1,'out'),(2,'in'),(2,'out'),(1,'in'),(1,'out'),(1,'in'),(2,'out'),(2,'in'),(2,'out'),(2,'in'),(1,'in'),(1,'in');
Query
SELECT SQL_CALC_FOUND_ROWS
channelid,
group_concat ( concat(name,':',channelid) )
FROM Demo
group by channelid;
SELECT FOUND_ROWS();
See the results the the fiddle
Please find below working code as per your requirement :
select tb.channelid, group_concat
(
concat(tb.name,':',tb.MyCol2Count)
) as v1
from
(Select tbl.channelid,tbl.name,(LENGTH(tbl.val) - LENGTH(REPLACE(tbl.val,",","")) + 1) AS MyCol2Count
from
(SELECT channelid, group_concat
(
concat(name,':',channelid)
) as val,name
FROM Demo
group by channelid,Name) as tbl) as tb group by tb.channelid
You can check on below screenshot : http://springinfosoft.com/code/Groupby_code.png

SQL: Sum of count statements containing where clause

I have 3 count statements, which I need to combine and take a sum of.
SELECT COUNT(status)
FROM tableA
WHERE env='test'
AND deploy_date='2016-10-19'
AND platform='MA'
AND server='B'
AND status='5';
SELECT COUNT(status)
FROM tableA
WHERE env='test'
AND deploy_date='2016-10-19'
AND platform='MA'
AND server='B'
AND status='3';
SELECT COUNT(status)
FROM tableA
WHERE env='test'
AND deploy_date='2016-10-19'
AND platform='MA'
AND server='B'
AND status='1';
I tried
SELECT (select count(status)
FROM tableA
WHERE env='test'
AND deploy_date='2016-10-19'
AND platform='MA'
AND server='B' and status='5'; ) +
(SELECT COUNT(status)
FROM tableA WHERE env='test'
AND deploy_date='2016-10-19'
AND platform='MA'
AND server='B' AND status='3';) +
(SELECT COUNT(status)
FROM tableA
WHERE env='test'
AND deploy_date='2016-10-19'
AND platform='MA'
AND server='B' AND status='1';)
But getting syntax error. What am I missing? Is there a better way to accomplish this in MySQL.
Thanks in advance
Here is one way to combine
SELECT count(1)
FROM tableA
WHERE env = 'test'
AND deploy_date = '2016-10-19'
AND platform = 'MA'
AND server = 'B'
AND status IN ( '5', '3', '1' );
Please try this one, it is very simple query.
SELECT status, count(status) from tableA
WHERE env='test' AND deploy_date='2016-10-19' AND platform='MA' AND server='B' AND status in ('1','3','5')
Group by status
above will return individual count and sum if you want sum of all then just remove group by clause.
SELECT count(status)
FROM tableA
WHERE env = 'test'
AND deploy_date = '2016-10-19'
AND platform = 'MA'
AND server = 'B'
AND status IN ( '5', '3', '1' );
You can combine the statement into one, status differ, rest all the filtration are same.
For status wise count, add group by clause Group By Status at the end of the SQL script.
SELECT Status,count(status)
FROM tableA
WHERE env = 'test'
AND deploy_date = '2016-10-19'
AND platform = 'MA'
AND server = 'B'
AND status IN ( '5', '3', '1' )
Group By Status

MySQL insert if select output <> Value

I'm writing a Logging System for Items where i track the Quantity and Type of various Objects.
And i need to write a Insert Query where it only imports if the Quantity (qty) has changed since the last time.
This is the Query to get the last inserted Quantity:
SELECT qty FROM `qty` WHERE object='object_name' AND type='type' ORDER BY UNIX_TIMESTAMP(timestamp) DESC LIMIT 1
But now how do i say: Import only if quantity given by Programm is not the Quantity given by the Query above
Edit:
Here is the Normal insert:
INSERT INTO `qty` (qty, object, type) VALUES ("quantity", "object_name", "type")
Edit:
I got it working now!
thanks everybody for the response! you guys are awesome :)
INSERT INTO qty (qty, object, type)
SELECT * FROM (SELECT 'qty-value', 'object-value', 'type-value') AS tmp
WHERE NOT EXISTS (
SELECT * FROM (SELECT qty FROM `qty` WHERE object = 'object-value' AND type = 'type-value' ORDER BY UNIX_TIMESTAMP( timestamp ) DESC LIMIT 1) as lastQTY WHERE qty = "qty-value"
) LIMIT 1;
If you want to insert new values, try matching the new values to the old values. If there is a match, then filter out the rows. I think the key is using insert . . . select rather than insert . . . values.
The following gives the idea:
INSERT INTO qty(qty, object, type)
select #quantity, #object_name", #type
from (select #quantity as quantity, #object_name as object_name, #type as type
) as newrow left outer join
(SELECT qty.*
FROM qty
WHERE object = #object_name AND type = #type
ORDER BY UNIX_TIMESTAMP(timestamp) DESC
LIMIT 1
) oldrow
on newrow.quantity = oldrow.quantity and
newrow.object_name = oldrow.object_name and
newrow.type = oldrow.type
where oldrow is null;
Think this would do it.
This takes your input values, joins that against a sub query to get the latest timestamp for the object and type, and then joins that against the qty table to get the value of the column qty for the latest timestamp and that the qty is the same as the new qty.
The WHERE clause is then checking that the value of the latest qty is NULL (ie, assuming the qty can not legitimatly be NULL there is no record found )
INSERT INTO `qty_test` (qty, object, type)
SELECT a.qty, a.object, a.type
FROM
(
SELECT 1 AS qty, 1 AS object, 1 AS type
) a
LEFT OUTER JOIN
(
SELECT object, type, MAX(timestamp) AS max_timestamp
FROM qty_test
GROUP BY object, type
) b
ON a.object = b.object
AND a.type = b.type
LEFT OUTER JOIN qty_test c
ON a.object = c.object
AND a.type = c.type
AND a.qty = c.qty
AND b.max_timestamp = c.timestamp
WHERE c.qty IS NULL

MYSQL INSERT IF SUMs > CONSTANT

I'm trying to insert a record if a sum of 3 user columns from 2 tables exceeds a constant.
I've searched all over, found you can't put user variables in IFs, WHERE's etc. Found you can't put SUMs in IFs, WHERE's etc. I'm at a total loss. Here's an example of my earlier bad code before unsuccessfully trying to use SUMs in WHEREs, if it helps:
SELECT SUM(num1) INTO #mun1 FROM table1 WHERE user = '0';
SELECT SUM(num2) INTO #mun2 FROM table1 WHERE user = '0';
SELECT SUM(num3) INTO #mun3 FROM table2 WHERE column1 = 'd' AND user = '0';
SET #mun4 = #mun1 - #mun2 - #mun3;
INSERT INTO table2 (user, column1, column2) VALUES ('0', 'd', '100') WHERE #mun4 >= 100;
Try this:
INSERT INTO table2 (user, column1, column2)
select '0', 'd', '100'
from dual
where (SELECT SUM(num1 + num2) FROM table1 WHERE user = '0') +
(SELECT SUM(num3) FROM table2 WHERE column1 = 'd' AND user = '0') > 100;
This is a case of the general solution for a "insert if condition" problem:
insert into ... select ... where condition
The select will only return rows if the condition is true, and importantly, will return no rows if false - meaning the insert only happens if the condition is true, otherwise nothing happens.
This is same as #Bohemian's answer, but you got to add a LIMIT clause to stop inserting multiple records, since select clause may return multiple records
INSERT INTO table2 (user, column1, column2)
SELECT '0', 'd', '100'
FROM dual
WHERE
(SELECT SUM(num1 - num2) FROM table1 WHERE user = '0')
(SELECT SUM(num3) FROM table2 WHERE column1 = 'd' AND user = '0') >
100
LIMIT 1