I hava a Table ,I can use
SELECT `event_id` FROM `event` WHERE 1
to get mulipie rows event_id , and I put event_id in this query
SET #event_id = XXXX;
SELECT * FROM(
(SELECT `event_id`,`author_id`,`latitude`,`longitude`,`type`,`rate`,`description`,`photo_id`, UNIX_TIMESTAMP(`timestamp`) AS `timestamp`
FROM `event`) AS `event`,
(SELECT COUNT(*) AS `thumb_up_count` FROM `thumb_event` WHERE `event_id` = #event_id AND `thumb_state` = 1) AS `thumb_up_count`,
(SELECT COUNT(*) AS `thumb_down_count` FROM `thumb_event` WHERE `event_id` = #event_id AND `thumb_state` = 2) AS `thumb_down_count`,
(SELECT IFNULL((SELECT `thumb_state` FROM `thumb_event` WHERE `event_id` = #event_id AND `user_id` = ?) , 0) AS `thumbed`) AS `thumbed`,
(SELECT COUNT(*) AS `comment_count` FROM `event_comment` WHERE `event_id` = #event_id) AS `comment_count`
) WHERE `event_id` = #event_id;
I can use SET #event_id = 0000; to set event_id , but how I can put all event_id from select in that query
If i understoods, maybe what you need it's an IN clause:
WHERE `event_id` IN (SELECT `event_id` FROM `event` WHERE 1);
Related
CREATE TABLE `user_activity` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`type` enum('request','response') DEFAULT NULL,
`data` longtext NOT NULL,
`created_at` datetime DEFAULT NULL,
`source` varchar(255) DEFAULT NULL,
`task_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
);
I have this data:-
Now I need to select all rows for user_id=527 where created_at value is the maximum. So I need the last 3 rows in this image.
I wrote this query:-
SELECT *
FROM user_activity
WHERE user_id = 527
AND source = 'E1'
AND task_name IN ( 'GetReportTask', 'StopMonitoringUserTask' )
AND created_at = (SELECT Max(created_at)
FROM user_activity
WHERE user_id = 527
AND source = 'E1'
AND task_name IN ( 'GetReportTask',
'StopMonitoringUserTask' ));
This is very inefficient because I am running the exact same query again as an inner query except that it disregards created_at. What's the right way to do this?
I would use a correlated subquery:
SELECT ua.*
FROM user_activity ua
WHERE ua.user_id = 527 AND source = 'E1' AND
ua.task_name IN ('GetReportTask', 'StopMonitoringUserTask' ) AND
ua.created_at = (SELECT MAX(ua2.created_at)
FROM user_activity ua2
WHERE ua2.user_id = ua.user_id AND
ua2.source = ua.source AND
ua2.task_name IN ( 'GetReportTask', 'StopMonitoringUserTask' )
);
Although this might seem inefficient, you can create an index on user_activity(user_id, source, task_name, created_at). With this index, the query should have decent performance.
Order by created_at desc and limit your query to return 1 row.
SELECT *
FROM user_activity
WHERE user_id = 527
AND source = 'E1'
AND task_name IN ( 'GetReportTask', 'StopMonitoringUserTask' )
ORDER BY created_at DESC
LIMIT 1;
I used EverSQL and applied my own changes to come up with this single-select query that uses self-join:-
SELECT *
FROM user_activity AS ua1
LEFT JOIN user_activity AS ua2
ON ua2.user_id = ua1.user_id
AND ua2.source = ua1.source
AND ua2.task_name IN ( 'GetReportTask', 'StopMonitoringUserTask' )
AND ua1.created_at < ua2.created_at
WHERE ua1.user_id = 527
AND ua1.source = 'E1'
AND ua1.task_name IN ( 'GetReportTask', 'StopMonitoringUserTask' )
AND ua2.created_at IS NULL;
However, I noticed that the response times of both queries were similar. I tried to use Explain to identify any performance differences; and from what I understood from its output, there are no noticeable differences because proper indexing is in place. So for readability and maintainability, I'll just use the nested query.
I have a parent-child relation for the following tables:
CREATE TABLE `pages` (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(100) NULL,
PRIMARY KEY ( id )
)
CREATE TABLE `pageObjects` (
id INT NOT NULL AUTO_INCREMENT,
object TEXT NULL,
lastChanged TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL,
fkPageId int NOT NULL,
PRIMARY KEY ( id )
)
The pages have a one:many relation with pageObjects.
Whenever the pageObjects records connected to a single page exceed 10, all records that are edited furthest in the past and exceeding the 10 must be deleted.
I wanted to do this in a single query, but I can't seem to figure this out...
This is how far I've gotten:
DELETE
FROM pageObjects
WHERE id NOT IN (
SELECT po.id, po.fkPageId FROM (
SELECT objects.fkPageId FROM (
SELECT COUNT(*) as count, fkPageId
FROM pageObjects
GROUP BY fkPageId
) objects
WHERE count > 10
) AS page
JOIN pageObjects po
ON page.fkPageId = po.fkPageId
AND po.lastChanged < (
SELECT MIN(lastChanged )
FROM pageObjects
WHERE fkPageId = po.fkPageId
GROUP BY fkPageId
ORDER BY lastChanged DESC
LIMIT 10
)
)
Sadly, the LIMIT bit in the bottom sub-query is not working the way I want to, because the MIN() function should be applied AFTER the LIMIT is applied.
So I tried that:
DELETE
FROM pageObjects
WHERE id NOT IN (
SELECT po.id, po.fkPageId FROM (
SELECT objects.fkPageId FROM (
SELECT COUNT(*) as count, fkPageId
FROM pageObjects
GROUP BY fkPageId
) objects
WHERE count > 10
) AS page
JOIN pageObjects po
ON page.fkPageId = po.fkPageId
AND po.lastChanged < (
SELECT MIN(lastChanged)
FROM (
SELECT lastChanged
FROM pageObjects
WHERE fkPageId = po.fkPageId
GROUP BY fkPageId
ORDER BY lastChanged DESC
LIMIT 10
)
)
)
But this is not possible, because the po.fkPageId is not available in the sub-query of the sub-query.
Is there any way to do this like this?
You can do this quite simply by counting the number of later entries for each id:
DELETE FROM pageObjects
WHERE id IN (
SELECT id FROM pageObjects po
WHERE (
SELECT count(id)
FROM pageObjects po2
WHERE po2.fkPageId = po.fkPageId
AND po2.lastChanged > po.lastChanged
) > 10
)
Check out what the select returns here:
http://www.sqlfiddle.com/#!9/f5218f/1/0
I have to following subquery
SELECT
(
SELECT SUM( `total_amount` )
FROM `civicrm_contribution`
WHERE `currency` = 'PCT'
AND `contact_id` = ( SELECT `id`FROM `civicrm_contact`
WHERE `first_name` = ''
UNION ALL
SELECT `contact_id` FROM `civicrm_membership`
WHERE `source` = '')
)
-
(
SELECT SUM(`fee_amount`)
FROM `civicrm_participant`
WHERE `fee_level`='puncte'
AND `contact_id` = (SELECT `id` FROM `civicrm_contact`
WHERE `first_name` =''
UNION ALL
SELECT `contact_id` FROM `civicrm_membership`
WHERE `source` = '')
)As RemainingPoints
and i don't know how to add the result to following queries
SELECT `civicrm_contact`.first_name,`civicrm_membership`.start_date, `civicrm_membership`.end_date, `civicrm_membership`.source FROM `civicrm_contact`, `civicrm_membership` WHERE `civicrm_contact`.id = `civicrm_membership`.contact_id AND `civicrm_membership`.source =''
UNION ALL
SELECT `civicrm_contact`.first_name,`civicrm_membership`.start_date, `civicrm_membership`.end_date, `civicrm_membership`.source FROM `civicrm_contact`, `civicrm_membership` WHERE `civicrm_contact`.id = `civicrm_membership`.contact_id AND `civicrm_contact`.first_name ='test1'
I would like that the "RemainingPoints" to be added at the end of the query
first_name ;start_date; end_date; source; "RemainingPoints"
SELECT *
FROM (SELECT `civicrm_contact`.first_name,`civicrm_membership`.start_date, `civicrm_membership`.end_date, `civicrm_membership`.source FROM `civicrm_contact`, `civicrm_membership` WHERE `civicrm_contact`.id = `civicrm_membership`.contact_id AND `civicrm_membership`.source =''
UNION ALL
SELECT `civicrm_contact`.first_name,`civicrm_membership`.start_date, `civicrm_membership`.end_date, `civicrm_membership`.source FROM `civicrm_contact`, `civicrm_membership` WHERE `civicrm_contact`.id = `civicrm_membership`.contact_id AND `civicrm_contact`.first_name ='test1'
) x
JOIN (SELECT (
SELECT SUM( `total_amount` )
FROM `civicrm_contribution`
WHERE `currency` = 'PCT'
AND `contact_id` = ( SELECT `id`FROM `civicrm_contact`
WHERE `first_name` = ''
UNION ALL
SELECT `contact_id` FROM `civicrm_membership`
WHERE `source` = '')
)
-
(
SELECT SUM(`fee_amount`)
FROM `civicrm_participant`
WHERE `fee_level`='puncte'
AND `contact_id` = (SELECT `id` FROM `civicrm_contact`
WHERE `first_name` =''
UNION ALL
SELECT `contact_id` FROM `civicrm_membership`
WHERE `source` = '')
) As RemainingPoints) y
I need to get payment sum for all period and for current month. There are two tables: category and transactions.
transactions:
id int(11)
category varchar(32)
dttm_added datetime
minus float
minus_currency varchar(32)
categories:
id int(11)
key varchar(32)
name varchar(50)
type varchar(1)
Here is my query:
select `key`, `id`, `name`, minus_month,month_cur
from `categories` as ct
left join (
select `category` as tr_ct_m, date_format(`dttm_trans`, '%Y%m') as dat, sum(`minus`) as minus_month, `minus_currency` as month_cur from `transactions` where dat = date_format(now(), '%Y%m')
) as tr_m on tr_m.tr_ct_m = ct.key
where `type` = '-'
I need to check clause in select before joining, because after sum of minus_month all dates are turning to Null.
Help plz
not sure if i understand you correctly,please try below:
select `ct`.`key`, `ct`.`id`, `ct`.`name`, tr_m.minus_month,tr_m.month_cur from
( select * from `categories` where `type` = '-') as ct
left join
( select `category` as tr_ct_m, date_format(`dttm_trans`, '%Y%m') as dat,
sum(`minus`) as minus_month, `minus_currency` as month_cur from `transactions`
where dat = date_format(now(), '%Y%m')
) as tr_m on tr_m.tr_ct_m = ct.key
I want to select all rows where WHERE (uid = {$uid} OR uid = **HERE** ) where **HERE** is the cids retreived from query 2 below.
Query 1:
SELECT * FROM `t_activities`
WHERE (`uid` = {$uid} OR `uid` = **HERE** )
AND `del` = 0
GROUP BY `fid`
ORDER BY `time` DESC
LIMIT 10
And Query 2:
SELECT `cid` FROM `t_con` WHERE `uid` = {$uid} AND `flag` = 1
SELECT * FROM `t_activities`
WHERE (`uid` = {$uid} OR `uid` in (SELECT `cid`
FROM `t_con`
WHERE `uid` = {$uid} AND `flag` = 1))
AND `del` = 0
GROUP BY `fid`
ORDER BY `time` DESC
LIMIT 10
You can do this as a join as well:
SELECT *
FROM `t_activities` ta left outer join
(SELECT `cid`
FROM `t_con`
WHERE `uid` = {$uid} AND `flag` = 1)
) tc
on ta = tc.cid
WHERE (`uid` = {$uid} OR tc.`uid` is not null) AND `del` = 0
GROUP BY `fid`
ORDER BY `time` DESC
LIMIT 10
By the way, as a SQL statement the "GROUP BY fid" looks very strange. This is allowed in mysql, but I think it is a bad practice. It is much better to be explicit about what you are doing:
SELECT fid, min(<field1>) as Field1, . . .
This helps prevent mistakes when you go back to the query or try to modify it.