I have a mysql query that returns user_name and sess_start from sess_active table if user_name exists in sess_active_tmp table.
Query below for above is working as inteded, but I also would like to retrieve data from sess_active_tmp table aswell. Since I execute another SELECT statement in EXISTS part, shouldn't I be able to retrieve data of this statement aswell?
Working query:
SELECT sess_main.user_name,
sess_main.sess_start
FROM sess_active AS sess_main
WHERE ( sess_main.user_name = 'testuser'
AND sess_main.sess_stop IS NULL )
AND EXISTS (SELECT user_name
FROM sess_active_tmp AS sess_temp
WHERE sess_temp.user_name = 'testuser'
AND sess_temp.sess_start =
sess_main.sess_start
AND sess_temp.sess_stop IS NULL)
Query I am trying to get it work;
SELECT sess_main.user_name,
sess_main.sess_start,
sess_temp.upload_byte,
sess_temp.download_byte,
FROM sess_active AS sess_main
WHERE ( sess_main.user_name = 'testuser'
AND sess_main.sess_stop IS NULL )
AND EXISTS (SELECT user_name
FROM sess_active_tmp AS sess_temp
WHERE sess_temp.user_name = 'testuser'
AND sess_temp.sess_start =
sess_main.sess_start
AND sess_temp.sess_stop IS NULL)
I also added sess_temp.upload_byte, sess_temp.download_byte to sess_temp select statement but it also doesn't work.
Is it only achievable with JOIN and if yes would it decrease performance? since this query will run like 2-3k times(users) every 2 minutes.
Thanks in advance.
EDIT: Query below does what I want to achieve but I have performance concerns, is it the best way to achieve what I want to do?
SELECT sess_main.user_name,
sess_main.sess_start,
sess_temp.upload_byte,
sess_temp.download,
FROM sess_active AS sess_main
INNER JOIN sess_active_tmp sess_temp
ON ( sess_temp.user_name = sess_main.user_name
AND sess_temp.sess_start = sess_main.sess_start
AND sess_temp.sess_stop IS NULL )
WHERE ( sess_main.user_name = 'testuser'
AND sess_main.sess_stop IS NULL )
AND EXISTS (SELECT user_name
FROM sess_active_tmp AS sess_temp
WHERE sess_temp.user_name = 'testuser'
AND sess_temp.sess_start = sess_main.sess_start
AND sess_temp.sess_stop IS NULL)
Im trying to change some records in my database but sadly my sql knowledge is a bit limited. After googling and reading stuff online I have managed to write a select statement in which i can find the records that I want to update but i dont understand the logic to write the update statement to do it. I have to make several similar update statements so I hope this one I can figure out the rest myself
This is the select statement I have:
SELECT
MG.id,
MG.status,
MG.fin,
MG.execDateTime,
EXISTS
(
SELECT 1
FROM Mtask T
JOIN MTaskHis TH ON TH.t_id= T.id
WHERE T.tg_id = MG.id
AND YEAR(TH.dateTime) = 2019
) AS hasExecStart,
NMG.id,
NMG.execDateTime,
EXISTS
(
SELECT 1
FROM Mtask T
JOIN MTaskHis TH ON TH.t_id = T.id
WHERE T.tg_id = NMG.id
AND YEAR(TH.dateTime) = 2019
) AS hasExecNext
FROM Management_Group MG
JOIN MT_Groupman MTGM ON
MG.tgm_id = MTGM.id
LEFT JOIN Management_Group NMG ON MTGM.id =
NMG.tgm_id AND YEAR(NMG.execDateTime) = 2019
JOIN Management_Man MM ON MTGM.man_id = MM.id
JOIN Location L ON MM.location_id = L.id
WHERE L.org_id = 69
AND MG.stat != 'DELETED'
AND YEAR(MG.execDateTime) = 2018
AND MM.Type= 9
AND MG.fin != 1
AND EXISTS
(
SELECT 1
FROM Mtask T
WHERE T.tg_id = MG.id
AND T.stat = 'execution'
)
HAVING hasExecNext = 0 AND hasExecStart = 1
I know standard updates in sql:
UPDATE <TABLENAME>
SET <fieldName> = <value>
WHERE <conditons>
Except I do not know how to convert this select statement I have made into an update statement, reason for that is:
- Where do I put the exist alias in the update statement
- I also dont understand when or where to put all the JOINS in the from statement
- What about the HAVING
What is the best way to do joined updates like this?
In an UPDATE you can join the table you want to update to a sub-query that contains your current query.
UPDATE YourTable t
JOIN
(
<< add your query here >>
) q ON q.SomeKeyField = t.SomeKeyField
SET t.FieldName = q.FieldNameFromSubquery,
t.OtherFieldName = q.OtherFieldNameFromSubquery
I have the following code and I'm trying to group the messages
Here is a picture of database table and how the groups should be
and here is the SQL statement
SELECT a.* FROM `user_messages` `a`
JOIN (
SELECT `sender`, MAX(`id`) `last_id` FROM `user_messages` WHERE `receiver` = '1' GROUP BY `sender`
) `b`
ON `a`.`sender` = `b`.`sender` AND `a`.`id` = `b`.`last_id`
WHERE `a`.`receiver` = '1'
ORDER BY `id` DESC
OUTPUT:
I want to get somehow the last record where "receiver" is not my id, but "sender" is and name receiver column as "id" or something.
...so what i want is following result:
id | msg
13852 123
48 Hello!
17 321
Here is a fiddle: http://sqlfiddle.com/#!9/e06d57/3/0
To map my generic answer to your particular use case (using example 1):
SELECT receiver AS id, msg
FROM user_messages outerTable
WHERE NOT EXISTS
( SELECT *
FROM user_messages innerTable
WHERE innerTable.sender = outerTable.sender
AND innerTable.receiver = outerTable.receiver
AND innerTable.added > outerTable.added
)
AND sender = 1
This is a very common use case. There are several ways to write this code. Depending on the SQL engine used, they will be of different speeds.
I will use fairly generic column names. Tweak as needed.
SELECT common_id, msg
FROM myTable outerTable
WHERE NOT EXISTS
( SELECT *
FROM myTable innerTable
WHERE innerTable.common_id = outerTable.common_id
AND innerTable.time > outerTable.time
)
Please note that if there are two rows with identical common_id and time columns, then both will show up in the output. You can replace the > with >= to hide both of those rows.
The other common approach is kind of difficult to make sense of, but here goes. Notice the similarities to the NOT EXISTS approach.
SELECT outerTable.common_id, outerTable.msg
FROM myTable outerTable
LEFT JOIN myTable innerTable
ON innerTable.common_id = outerTable.common_id
AND innerTable.time > outerTable.time
WHERE innerTable.common_id IS NULL
According to your description, you seem to want something like this:
select um.receiver as id, um.msg
from user_messages um
where um.sender = 1 and
um.id = (select max(um2.id)
from user_messages um2
where um2.msg = um.msg and um2.receiver <> 1 and um.sender = 1
);
It doesn't produce the desired output, but that is because the output is inconsistent with the text description.
I have two select queries like this:
SELECT COUNT(WARD_id)
FROM IP_Admission
WHERE (Status = 'V' OR Status = 'D') AND WARD_ID = 1
SELECT BED_STRENGTH
FROM Ward_Master
WHERE Ward_ID = 1
Output of the query is
2
6
Now I need answer 4. Any help appreciated.
You may try like this:
declare #a int
declare #b int
SELECT #a = COUNT(WARD_id) FROM IP_Admission WHERE (Status='V' OR Status='D') AND WARD_ID=1
SELECT #b = BED_STRENGTH FROM Ward_Master WHERE Ward_ID=1
select #b - #a
select count(i.ward_id) - w.bed_strength as Diff from
ip_admission i join ward_master w on w.ward_id=i.ward_id
where (status='V' or status='D') and i.ward_id=1
group by w.bed_strength
Try This for all ward ID's
SELECT M.Ward_ID,BED_STRENGTH -COUNT(WARD_id)
FROM IP_Admission A
JOIN Ward_Master M ON A.WARD_ID = M.WARD_ID
WHERE (A.Status='V' OR A.Status='D')
GROUP BY M.Ward_ID
You can use inner join like this. Please let me know if this doesn't work.
create table #Tmp1
(
Ward_Id INT,
Status Char(1)
)
create table #tmp2
(
Ward_Id INT,
BED_STRENGTH INT
)
INSERT INTO #Tmp1 VALUES (1,'V'),(1,'D')
INSERT INTO #tmp2 VALUES (1,6)
SELECT COUNT(WARD_id)
FROM #Tmp1
WHERE (Status='V' OR Status='D') AND WARD_ID=1
SELECT BED_STRENGTH FROM #Tmp2 WHERE Ward_ID=1
SELECT #tmp2.BED_STRENGTH - COUNT(#tmp1.WARD_id)
FROM #Tmp1
INNER JOIN #tmp2 ON #tmp2.Ward_Id = #tmp1.Ward_Id
WHERE (Status='V' OR Status='D') AND #tmp1.WARD_ID=1
GROUP BY #tmp2.BED_STRENGTH
DROP TABLE #Tmp1
DROP TABLE #Tmp2
Since you are pulled these values from two different tables, the best way to do this will to be to join the table on ward id.
SELECT wm.BED_STRENGTH - COUNT(ip.WARD_id)
FROM Ward_Master wm inner join IP_Admission ip
On wm.ward_id = ip.ward_id
WHERE (ip.Status='V' OR ip.Status='D')
Group by wm.BED_STRENGTH
This should work, but it might not depending on the schema. The advantage with this method is that it will find the value for all ward ids.
The simplest solution is:
SELECT (subquery1) - (subquery2)
This will only show the value for the ward id that you specify.
Thanks everyone i solved my query as
SELECT M.Bed_Strength - COUNT(A.WARD_id) as diff
FROM IP_Admission A
JOIN Ward_Master M ON A.WARD_ID = M.WARD_ID
WHERE (A.Status='V' OR A.Status='D') and M.Ward_ID=1 group by M.Bed_Strength;
I need to check (from the same table) if there is an association between two events based on date-time.
One set of data will contain the ending date-time of certain events and the other set of data will contain the starting date-time for other events.
If the first event completes before the second event then I would like to link them up.
What I have so far is:
SELECT name as name_A, date-time as end_DTS, id as id_A
FROM tableA WHERE criteria = 1
SELECT name as name_B, date-time as start_DTS, id as id_B
FROM tableA WHERE criteria = 2
Then I join them:
SELECT name_A, name_B, id_A, id_B,
if(start_DTS > end_DTS,'VALID','') as validation_check
FROM tableA
LEFT JOIN tableB ON name_A = name_B
Can I then, based on my validation_check field, run a UPDATE query with the SELECT nested?
You can actually do this one of two ways:
MySQL update join syntax:
UPDATE tableA a
INNER JOIN tableB b ON a.name_a = b.name_b
SET validation_check = if(start_dts > end_dts, 'VALID', '')
-- where clause can go here
ANSI SQL syntax:
UPDATE tableA SET validation_check =
(SELECT if(start_DTS > end_DTS, 'VALID', '') AS validation_check
FROM tableA
INNER JOIN tableB ON name_A = name_B
WHERE id_A = tableA.id_A)
Pick whichever one seems most natural to you.
UPDATE
`table1` AS `dest`,
(
SELECT
*
FROM
`table2`
WHERE
`id` = x
) AS `src`
SET
`dest`.`col1` = `src`.`col1`
WHERE
`dest`.`id` = x
;
Hope this works for you.
Easy in MySQL:
UPDATE users AS U1, users AS U2
SET U1.name_one = U2.name_colX
WHERE U2.user_id = U1.user_id
If somebody is seeking to update data from one database to another no matter which table they are targeting, there must be some criteria to do it.
This one is better and clean for all levels:
UPDATE dbname1.content targetTable
LEFT JOIN dbname2.someothertable sourceTable ON
targetTable.compare_field= sourceTable.compare_field
SET
targetTable.col1 = sourceTable.cola,
targetTable.col2 = sourceTable.colb,
targetTable.col3 = sourceTable.colc,
targetTable.col4 = sourceTable.cold
Traaa! It works great!
With the above understanding, you can modify the set fields and "on" criteria to do your work. You can also perform the checks, then pull the data into the temp table(s) and then run the update using the above syntax replacing your table and column names.
Hope it works, if not let me know. I will write an exact query for you.
UPDATE
receipt_invoices dest,
(
SELECT
`receipt_id`,
CAST((net * 100) / 112 AS DECIMAL (11, 2)) witoutvat
FROM
receipt
WHERE CAST((net * 100) / 112 AS DECIMAL (11, 2)) != total
AND vat_percentage = 12
) src
SET
dest.price = src.witoutvat,
dest.amount = src.witoutvat
WHERE col_tobefixed = 1
AND dest.`receipt_id` = src.receipt_id ;
Hope this will help you in a case where you have to match and update between two tables.
I found this question in looking for my own solution to a very complex join. This is an alternative solution, to a more complex version of the problem, which I thought might be useful.
I needed to populate the product_id field in the activities table, where activities are numbered in a unit, and units are numbered in a level (identified using a string ??N), such that one can identify activities using an SKU ie L1U1A1. Those SKUs are then stored in a different table.
I identified the following to get a list of activity_id vs product_id:-
SELECT a.activity_id, w.product_id
FROM activities a
JOIN units USING(unit_id)
JOIN product_types USING(product_type_id)
JOIN web_products w
ON sku=CONCAT('L',SUBSTR(product_type_code,3), 'U',unit_index, 'A',activity_index)
I found that that was too complex to incorporate into a SELECT within mysql, so I created a temporary table, and joined that with the update statement:-
CREATE TEMPORARY TABLE activity_product_ids AS (<the above select statement>);
UPDATE activities a
JOIN activity_product_ids b
ON a.activity_id=b.activity_id
SET a.product_id=b.product_id;
I hope someone finds this useful
UPDATE [table_name] AS T1,
(SELECT [column_name]
FROM [table_name]
WHERE [column_name] = [value]) AS T2
SET T1.[column_name]=T2.[column_name] + 1
WHERE T1.[column_name] = [value];
You can update values from another table using inner join like this
UPDATE [table1_name] AS t1 INNER JOIN [table2_name] AS t2 ON t1.column1_name] = t2.[column1_name] SET t1.[column2_name] = t2.column2_name];
Follow here to know how to use this query http://www.voidtricks.com/mysql-inner-join-update/
or you can use select as subquery to do this
UPDATE [table_name] SET [column_name] = (SELECT [column_name] FROM [table_name] WHERE [column_name] = [value]) WHERE [column_name] = [value];
query explained in details here http://www.voidtricks.com/mysql-update-from-select/
You can use:
UPDATE Station AS st1, StationOld AS st2
SET st1.already_used = 1
WHERE st1.code = st2.code
For same table,
UPDATE PHA_BILL_SEGMENT AS PHA,
(SELECT BILL_ID, COUNT(REGISTRATION_NUMBER) AS REG
FROM PHA_BILL_SEGMENT
GROUP BY REGISTRATION_NUMBER, BILL_DATE, BILL_AMOUNT
HAVING REG > 1) T
SET PHA.BILL_DATE = PHA.BILL_DATE + 2
WHERE PHA.BILL_ID = T.BILL_ID;
I had an issue with duplicate entries in one table itself. Below is the approaches were working for me. It has also been advocated by #sibaz.
Finally I solved it using the below queries:
The select query is saved in a temp table
IF OBJECT_ID(N'tempdb..#New_format_donor_temp', N'U') IS NOT NULL
DROP TABLE #New_format_donor_temp;
select *
into #New_format_donor_temp
from DONOR_EMPLOYMENTS
where DONOR_ID IN (
1, 2
)
-- Test New_format_donor_temp
-- SELECT *
-- FROM #New_format_donor_temp;
The temp table is joined in the update query.
UPDATE de
SET STATUS_CD=de_new.STATUS_CD, STATUS_REASON_CD=de_new.STATUS_REASON_CD, TYPE_CD=de_new.TYPE_CD
FROM DONOR_EMPLOYMENTS AS de
INNER JOIN #New_format_donor_temp AS de_new ON de_new.EMP_NO = de.EMP_NO
WHERE
de.DONOR_ID IN (
3, 4
)
I not very experienced with SQL please advise any better approach you know.
Above queries are for MySql server.
if you are updating from a complex query. The best thing is create temporary table from the query, then use the temporary table to update as one query.
DROP TABLE IF EXISTS cash_sales_sums;
CREATE TEMPORARY TABLE cash_sales_sums as
SELECT tbl_cash_sales_documents.batch_key, COUNT(DISTINCT tbl_cash_sales_documents.cash_sale_number) no_of_docs,
SUM(tbl_cash_sales_documents.paid_amount) paid_amount, SUM(A.amount - tbl_cash_sales_documents.bonus_amount - tbl_cash_sales_documents.discount_given) amount,
SUM(A.recs) no_of_entries FROM
tbl_cash_sales_documents
RIGHT JOIN(
SELECT
SUM(
tbl_cash_sales_transactions.amount
)amount,
tbl_cash_sales_transactions.cash_sale_document_id,
COUNT(transaction_id)recs
FROM
tbl_cash_sales_transactions
GROUP BY
tbl_cash_sales_transactions.cash_sale_document_id
)A ON A.cash_sale_document_id = tbl_cash_sales_documents.cash_sale_id
GROUP BY
tbl_cash_sales_documents.batch_key
ORDER BY batch_key;
UPDATE tbl_cash_sales_batches SET control_totals = (SELECT amount FROM cash_sales_sums WHERE cash_sales_sums.batch_key = tbl_cash_sales_batches.batch_key LIMIT 1),
expected_number_of_documents = (SELECT no_of_docs FROM cash_sales_sums WHERE cash_sales_sums.batch_key = tbl_cash_sales_batches.batch_key),
computer_number_of_documents = expected_number_of_documents, computer_total_amount = control_totals
WHERE batch_key IN (SELECT batch_key FROM cash_sales_sums);
INSERT INTO all_table
SELECT Orders.OrderID,
Orders.CustomerID,
Orders.Amount,
Orders.ProductID,
Orders.Date,
Customer.CustomerName,
Customer.Address
FROM Orders
JOIN Customer ON Orders.CustomerID=Customer.CustomerID
WHERE Orders.OrderID not in (SELECT OrderID FROM all_table)