I have this:
SELECT users.first_name,
users.last_name,
family_products.costs_obj
FROM users
JOIN family_products
ON users.family_id = family_products.family_id
WHERE users.family_id IN (SELECT family_id
FROM employer_families
WHERE employer_id = 117)
AND family_products.product_id IN (SELECT id
FROM market_products
WHERE type = "medicalplan")
AND users.first_name = 'alexandre'
And i need to be able to update cost_obj to = '' how would i run this select as an update?
Although I have not been able to test this, I think this is what you need:
UPDATE fp
SET fp.costs_obj = ''
FROM
users u
JOIN family_products fp ON u.family_id = fp.family_id
WHERE
u.family_id IN
(
SELECT
family_id
FROM
employer_families
WHERE
employer_id = 117
)
AND
fp.product_id IN
(
SELECT
id
FROM
market_products
WHERE
type = "medicalplan"
)
AND
u.first_name = 'alexandre';
Didn't test this since I don't know the schema, but you can try this:
UPDATE family_products
SET costs_obj = ''
WHERE costs_obj IN(
SELECT
family_products.costs_obj
FROM users
JOIN family_products
ON users.family_id = family_products.family_id
WHERE users.family_id IN (SELECT family_id
FROM employer_families
WHERE employer_id = 117)
AND family_products.product_id IN (SELECT id
FROM market_products
WHERE type = "medicalplan")
AND users.first_name = 'alexandre'
)
Related
I had an error in mysql as picture. please help me
sql code is following:
UPDATE
tbl_users AS Users
SET
Users.money_current = Users.money_current +
CASE
WHEN TempTbl.money_info IS NULL
THEN 0
ELSE TempTbl.money_info
END
LEFT JOIN
(SELECT
userId,
SUM(bet_money * bet_rate) AS money_info
FROM
tbl_betting
WHERE ROUND = 'xxx'
AND is_win = 1
GROUP BY userId) AS TempTbl
ON Users.userId = TempTbl.userId
FROM tbl_users AS Users;
This is the correct syntax:
UPDATE tbl_users AS Users
LEFT JOIN (
SELECT userId, SUM(bet_money * bet_rate) AS money_info
FROM tbl_betting WHERE ROUND = '965802' AND is_win = 1
GROUP BY userId
) AS TempTbl ON Users.userId = TempTbl.userId
SET Users.money_current = Users.money_current + COALESCE(TempTbl.money_info, 0)
I also changed that CASE expression with COALESCE().
But I think an INNER JOIN would also work in your case, since the unmatched rows of the LEFT JOIN that you use do not change the value of money_current.
I'm not sure how to make the following SQL query more efficient. Right now, the query is taking 8 - 12 seconds on a pretty fast server, but that's not close to fast enough for a Website when users are trying to load a page with this code on it. It's looking through tables with many rows, for instance the "Post" table has 717,873 rows. Basically, the query lists all Posts related to what the user is following (newest to oldest).
Is there a way to make it faster by only getting the last 20 results total based on PostTimeOrder?
Any help would be much appreciated or insight on anything that can be done to improve this situation. Thank you.
Here's the full SQL query (lots of nesting):
SELECT DISTINCT p.Id, UNIX_TIMESTAMP(p.PostCreationTime) AS PostCreationTime, p.Content AS Content, p.Bu AS Bu, p.Se AS Se, UNIX_TIMESTAMP(p.PostCreationTime) AS PostTimeOrder
FROM Post p
WHERE (p.Id IN (SELECT pc.PostId
FROM PostCreator pc
WHERE (pc.UserId IN (SELECT uf.FollowedId
FROM UserFollowing uf
WHERE uf.FollowingId = '100')
OR pc.UserId = '100')
))
OR (p.Id IN (SELECT pum.PostId
FROM PostUserMentions pum
WHERE (pum.UserId IN (SELECT uf.FollowedId
FROM UserFollowing uf
WHERE uf.FollowingId = '100')
OR pum.UserId = '100')
))
OR (p.Id IN (SELECT ssp.PostId
FROM SStreamPost ssp
WHERE (ssp.SStreamId IN (SELECT ssf.SStreamId
FROM SStreamFollowing ssf
WHERE ssf.UserId = '100'))
))
OR (p.Id IN (SELECT psm.PostId
FROM PostSMentions psm
WHERE (psm.StockId IN (SELECT sf.StockId
FROM StockFollowing sf
WHERE sf.UserId = '100' ))
))
UNION ALL
SELECT DISTINCT p.Id AS Id, UNIX_TIMESTAMP(p.PostCreationTime) AS PostCreationTime, p.Content AS Content, p.Bu AS Bu, p.Se AS Se, UNIX_TIMESTAMP(upe.PostEchoTime) AS PostTimeOrder
FROM Post p
INNER JOIN UserPostE upe
on p.Id = upe.PostId
INNER JOIN UserFollowing uf
on (upe.UserId = uf.FollowedId AND (uf.FollowingId = '100' OR upe.UserId = '100'))
ORDER BY PostTimeOrder DESC;
Changing your p.ID in (...) predicates to existence predicates with correlated subqueries may help. Also since both halves of your union all query are pulling from the Post table and possibly returning nearly identical records you might be able to combine the two into one query by left outer joining to UserPostE and adding upe.PostID is not null as an OR condition in the WHERE clause. UserFollowing will still inner join to UPE. If you want the same Post record twice once with upe.PostEchoTime and once with p.PostCreationTime as the PostTimeOrder you'll need keep the UNION ALL
SELECT
DISTINCT -- <<=- May not be needed
p.Id
, UNIX_TIMESTAMP(p.PostCreationTime) AS PostCreationTime
, p.Content AS Content
, p.Bu AS Bu
, p.Se AS Se
, UNIX_TIMESTAMP(coalesce( upe.PostEchoTime
, p.PostCreationTime)) AS PostTimeOrder
FROM Post p
LEFT JOIN UserPostE upe
INNER JOIN UserFollowing uf
on (upe.UserId = uf.FollowedId AND
(uf.FollowingId = '100' OR
upe.UserId = '100'))
on p.Id = upe.PostId
WHERE upe.PostID is not null
or exists (SELECT 1
FROM PostCreator pc
WHERE pc.PostId = p.ID
and pc.UserId = '100'
or exists (SELECT 1
FROM UserFollowing uf
WHERE uf.FollowedId = pc.UserID
and uf.FollowingId = '100')
)
OR exists (SELECT 1
FROM PostUserMentions pum
WHERE pum.PostId = p.ID
and pum.UserId = '100'
or exists (SELECT 1
FROM UserFollowing uf
WHERE uf.FollowedId = pum.UserId
and uf.FollowingId = '100')
)
OR exists (SELECT 1
FROM SStreamPost ssp
WHERE ssp.PostId = p.ID
and exists (SELECT 1
FROM SStreamFollowing ssf
WHERE ssf.SStreamId = ssp.SStreamId
and ssf.UserId = '100')
)
OR exists (SELECT 1
FROM PostSMentions psm
WHERE psm.PostId = p.ID
and exists (SELECT
FROM StockFollowing sf
WHERE sf.StockId = psm.StockId
and sf.UserId = '100' )
)
ORDER BY PostTimeOrder DESC
The from section could alternatively be rewritten to also use an existence clause with a correlated sub query:
FROM Post p
LEFT JOIN UserPostE upe
on p.Id = upe.PostId
and ( upe.UserId = '100'
or exists (select 1
from UserFollowing uf
where uf.FollwedID = upe.UserID
and uf.FollowingId = '100'))
Turn IN ( SELECT ... ) into a JOIN .. ON ... (see below)
Turn OR into UNION (see below)
Some the tables are many:many mappings? Such as SStreamFollowing? Follow the tips in http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table
Example of IN:
SELECT ssp.PostId
FROM SStreamPost ssp
WHERE (ssp.SStreamId IN (
SELECT ssf.SStreamId
FROM SStreamFollowing ssf
WHERE ssf.UserId = '100' ))
-->
SELECT ssp.PostId
FROM SStreamPost ssp
JOIN SStreamFollowing ssf ON ssp.SStreamId = ssf.SStreamId
WHERE ssf.UserId = '100'
The big WHERE with all the INs becomes something like
JOIN ( ( SELECT pc.PostId AS id ... )
UNION ( SELECT pum.PostId ... )
UNION ( SELECT ssp.PostId ... )
UNION ( SELECT psm.PostId ... ) )
Get what you can done of that those suggestions, then come back for more advice if you still need it. And bring SHOW CREATE TABLE with you.
I have a quite complex Mysql query:
SELECT
metabase_field.description, rows_to_copy.description,
metabase_field.display_name, rows_to_copy.display_name
FROM
metabase_field LEFT JOIN (select id as table_id, name as t_name from metabase_table) metabase_field_table ON metabase_field.table_id=metabase_field_table.table_id,
(
SELECT metabase_field.name as name, metabase_field_table.t_name as t_name, metabase_field.display_name as display_name, metabase_field.description as description, metabase_field.special_type as type
FROM metabase_field
LEFT JOIN (select id as table_id, name as t_name, db_id, active, visibility_type from metabase_table) metabase_field_table ON metabase_field.table_id = metabase_field_table.table_id
LEFT JOIN metabase_database metabase_field_table_database ON metabase_field_table.db_id = metabase_field_table_database.id
where metabase_field_table.active=1 and metabase_field_table.visibility_type is null and metabase_field_table_database.name = 'Prod'
) as rows_to_copy
WHERE
metabase_field_table.table_id IN (
SELECT distinct(metabase_table.id) as ids
from metabase_table
LEFT JOIN metabase_database metabase_table_database ON metabase_table.db_id = metabase_table_database.id
where metabase_table_database.name = 'Dev' and metabase_table.active=1 and metabase_table.visibility_type is null
)
and metabase_field_table.t_name = rows_to_copy.t_name
and metabase_field.name = rows_to_copy.name
This returns a table looking a bit like this:
+-------------+-------------+--------------+--------------+
| description | description | display_name | display_name |
+-------------+-------------+--------------+--------------+
| NULL | to copy | Application | Application |
Without going to deep into details, I just wanted to copty results from rows_to_copy to metabase_field fields, which means to set:
metabase_field.description = rows_to_copy.description,
metabase_field.display_name = rows_to_copy.display_name
I tried to just change SELECT to UPDATE:
UPDATE
metabase_field LEFT JOIN (select id as table_id, name as t_name from metabase_table) metabase_field_table ON metabase_field.table_id=metabase_field_table.table_id,
(
SELECT metabase_field.name as name, metabase_field_table.t_name as t_name, metabase_field.display_name as display_name, metabase_field.description as description, metabase_field.special_type as type
FROM metabase_field
LEFT JOIN (select id as table_id, name as t_name, db_id, active, visibility_type from metabase_table) metabase_field_table ON metabase_field.table_id = metabase_field_table.table_id
LEFT JOIN metabase_database metabase_field_table_database ON metabase_field_table.db_id = metabase_field_table_database.id
where metabase_field_table.active=1 and metabase_field_table.visibility_type is null and metabase_field_table_database.name = 'Prod'
) as rows_to_copy
SET
metabase_field.description = rows_to_copy.description,
metabase_field.display_name = rows_to_copy.display_name
WHERE
metabase_field_table.table_id IN (
SELECT distinct(metabase_table.id) as ids
from metabase_table
LEFT JOIN metabase_database metabase_table_database ON metabase_table.db_id = metabase_table_database.id
where metabase_table_database.name = 'Dev' and metabase_table.active=1 and metabase_table.visibility_type is null
)
and metabase_field_table.t_name = rows_to_copy.t_name
and metabase_field.name = rows_to_copy.name
;
But this query doesn't seem to change anything - the results stay the way they were. Is there any simple way to make it work?
After some formating I realize if almost imposible keep track of table names. use shorter and different alias to avoid bugs. I try to improve the rest of the code but too much work
I think the problem is the update. Update table should have the alias MF, and you SET MF.<field>
If that doesnt work, remove the WHERE and see if you UPDATE something. Of course only if you can do testing on those tables.
If that doesnt work, start with a single table and add one join at each time.
UPDATE metabase_field MF -- main alias for table to update.
LEFT JOIN (SELECT id as table_id, name as t_name
FROM metabase_table) MT1
ON MF.table_id = MT1.table_id
CROSS JOIN ( SELECT MF1.name as name,
MT2.t_name as t_name,
MF1.display_name as display_name,
MF1.description as description,
MF1.special_type as type
FROM metabase_field MF1
LEFT JOIN (SELECT id as table_id,
name as t_name,
db_id, active,
visibility_type
from metabase_table) MT2
ON MF1.table_id = MT2.table_id
LEFT JOIN metabase_database MD
ON MT2.db_id = MD.id
WHERE MT2.active = 1
and MT2.visibility_type is null
and MD.name = 'Prod'
) as rows_to_copy
SET
MF.description = rows_to_copy.description,
MF.display_name = rows_to_copy.display_name
WHERE
metabase_field_table.table_id IN (
SELECT distinct(metabase_table.id) as ids
from metabase_table
LEFT JOIN metabase_database MB
ON MT2.db_id = MB.id
WHERE MB.name = 'Dev'
and MT2.active=1
and MT2.visibility_type is null
)
and metabase_field_table.t_name = rows_to_copy.t_name
and metabase_field.name = rows_to_copy.name
;
Update metabase_field set metabase_field.description=
rows_to_copy.description, metabase_field.display_name=
rows_to_copy.display_name LEFT JOIN (select id as table_id, name as
t_name from metabase_table) metabase_field_table ON
metabase_field.table_id=metabase_field_table.table_id, ( SELECT
metabase_field.name as name, metabase_field_table.t_name as t_name,
metabase_field.display_name as display_name,metabase_field.description as description, metabase_field.special_type
as type FROM metabase_field LEFT JOIN (select id as table_id, name as
t_name, db_id, active, visibility_type from metabase_table)
metabase_field_table ON metabase_field.table_id =
metabase_field_table.table_id LEFT JOIN metabase_database
metabase_field_table_database ON metabase_field_table.db_id =
metabase_field_table_database.id where metabase_field_table.active=1
and metabase_field_table.visibility_type is null and
metabase_field_table_database.name = 'Prod' ) as rows_to_copy WHERE
metabase_field_table.table_id IN ( SELECT distinct(metabase_table.id)
as ids from metabase_table LEFT JOIN metabase_database
metabase_table_database ON metabase_table.db_id =
metabase_table_database.id where metabase_table_database.name = 'Dev'
and metabase_table.active=1 and metabase_table.visibility_type is null
) and metabase_field_table.t_name = rows_to_copy.t_name and
metabase_field.name = rows_to_copy.name
Try this
Here is my query:
SELECT *
FROM messages
WHERE status = 1
AND (
poster IN (SELECT thing FROM follows WHERE follower = :uid AND type = 3)
OR
topic_id IN (SELECT thing FROM follows WHERE follower = :uid AND type = 1)
)
ORDER BY post_date DESC LIMIT 0, 20
I want to know which clause the rows come from. From the poster IN (...) part or the topic_id IN (...) part? How can I do that?
A straightforward way:
SELECT *
, CASE WHEN poster IN (SELECT thing FROM follows WHERE follower = :uid AND type = 3) THEN 'poster'
ELSE 'topic_id' END AS from_clause
FROM messages <..>
Another way :
SELECT m.*
, CASE WHEN t1.thing IS NULL THEN 'topic_id' ELSE `poster` END AS from_clause
FROM messages m
LEFT JOIN (SELECT thing FROM follows WHERE follower = :uid AND type = 3) t1 ON m.poster = t1.thing
LEFT JOIN (SELECT thing FROM follows WHERE follower = :uid AND type = 1) t2 ON m.topic_id = t2.thing
WHERE m.status = 1 AND (t1.thing IS NOT NULL OR t2.thing IS NOT NULL)
I am new to SQL. Can someone help to convert this query, so it uses join syntax?
SELECT groups.name,
users.firstname,
users.lastname,
users.emailaddress,
groupmembers.userid,
reminders.groupid,
reminders.ownerid,
reminderdetails.recno,
reminderdetails.cardid,
reminderdetails.message
FROM reminderdetails,
reminders,
groupmembers,
users,
groups
WHERE assocdate = 'Y'
AND ( reminder1 != 99
AND ( Datediff(reminderdate, '2011-09-22') = reminder1 )
OR ( reminder2 != 99
AND Datediff(reminderdate, '2011-09-22') = reminder2 ) )
AND reminders.cardid = reminderdetails.cardid
AND groupmembers.groupid = reminders.groupid
AND groupmembers.sendemail = 'Y'
AND users.recno = groupmembers.userid
AND groups.recno = reminders.groupid
Try this:
SELECT g.name,
uu.firstname,
uu.lastname,
uu.emailaddress,
gp.userid,
rm.groupid,
rm.ownerid,
rd.recno,
rd.cardid,
rd.message
FROM reminderdetails rd
JOIN reminders rm on rm.cardid=rd.cardId
JOIN groupmembers gp on gp.groupid=rm.groupId and gp.sendemail='Y'
JOIN users uu on uu.recNo=gp.userId,
JOIN groups g ON g.recno=rm.groupId
WHERE assocdate = 'Y'
AND ( reminder1 != 99
AND ( Datediff(reminderdate, '2011-09-22') = reminder1 )
OR ( reminder2 != 99
AND Datediff(reminderdate, '2011-09-22') = reminder2 ) )
Bit of a guess without knowing your table structure, but I think this seems about right.
Edit: Just seen the other one; I'd generally prefer to not load up the JOIN with too many clauses, as you end up going hunting all over the place when you want to find out what WHERE clauses are being applied. If possible, I think it's better to keep JOINs containing just the JOIN and put the rest into the WHERE.
I'm sure someone else can come along and shoot me down on that one, but that's my take on it :)
SELECT groups.name,
users.firstname,
users.lastname,
users.emailaddress,
groupmembers.userid,
reminders.groupid,
reminders.ownerid,
reminderdetails.recno,
reminderdetails.cardid,
reminderdetails.message
FROM groups
INNER JOIN groupmembers ON groups.groupid = groupmembers.groupid
INNER JOIN users ON groupmembers.userid = users.userid
INNER JOIN reminders ON users.userid = reminders.ownderid
INNER JOIN reminderdetails ON reminders.cardid = reminderdetails.cardid
WHERE assocdate = 'Y'
AND ( reminder1 != 99
AND ( Datediff(reminderdate, '2011-09-22') = reminder1 )
OR ( reminder2 != 99
AND Datediff(reminderdate, '2011-09-22') = reminder2 ) )
AND groupmembers.sendemail = 'Y'