Hello, you see here a screenshot of the table-structure, which I want to extract information from. It is a table from a messaging-system.
Two users, which write each other messages get a unique msgconv id.
Now, I would like to get the latest msg from each msgconv where a specific user is involved in, but the msg is not allowed to be deleted by the specific user.
This is my query at the moment:
SELECT v1.msgconv
, v1.timesent
, v1.msg
, v1.msgfrom
, v1.msgto
, v1.msgdel_sender
, v1.msgdel_receiver
FROM msg v1
LEFT
JOIN msg v2
ON v1.msgconv = v2.msgconv
AND v1.timesent < v2.timesent
WHERE v1.msgfrom = 69
AND v1.msgdel_sender = 0
OR v1.msgto = 69
AND v1.msgdel_receiver = 0
ORDER
BY timesent DESC
With this query I get 14 results and I don´t know why. What I should get is only the latest msg of each msgconv.
Can please someone help me with this, thank you
I would like to get the latest msg from each msgconv where a specific user is involved
If you are running MySQL 8.0, you can use ROW_NUMBER() to identify the records to display:
SELECT *
FROM (
SELECT
m.*,
ROW_NUMBER() OVER(PARTITION BY msgconv ORDER BY timestamp DESC) rn
FROM msg m
WHERE
( msgfrom = 69 AND msgdel_sender = 0 )
OR ( msgto = 69 AND msgdel_receiver = 0 )
) x
In earlier versions, you can use a NOT EXISTS condition with a correlated subquery:
SELECT *
FROM msg m
WHERE
(
( msgfrom = 69 AND msgdel_sender = 0 )
OR ( msgto = 69 AND msgdel_receiver = 0 )
)
AND NOT EXISTS (
SELECT 1
FROM msg m1
WHERE
(
( m1.msgfrom = 69 AND m1.msgdel_sender = 0 )
OR ( m1.msgto = 69 AND m1.msgdel_receiver = 0 )
)
AND m1.msgconv = m.msgconv
AND m1.timestamp > m.timestamp
)
The query starts by selecting all records that belong to the relevant user. Then, the NOT EXISTS condition filters out every record but the latest in each group of record having the same msgconv.
Related
I'm using vbulletin 5 and getting message from the host that MYSQL Query was killed because it was running over 1 minutes .. I looked at the query and feel there is something wrong with it .. though I don't have enough experience to judge
here is the query ..
SELECT DISTINCT node.starter AS nodeid
FROM node as node
JOIN closure AS closure ON node.nodeid = closure.child
LEFT JOIN node AS starter
ON starter.nodeid = IF(node.starter = 0, node.nodeid, node.starter)
WHERE node.contenttypeid <> 19
AND node.contenttypeid IN ('22','26','23','21','20','25')
AND closure.parent = '2'
AND node.nodeid <> closure.parent
AND node.contenttypeid <> '15'
AND node.userid <> '28030'
AND (node.public_preview = 1
OR
(
(
(
(
starter.parentid IN (1,2,3,6,13,14,15,16,17,18,19,20,21,22,23,24,25,26,247197,257065,7,8,9,12,51,59,62,27,32,33,36,44,45,50,35,34,37,38,39,40,61,60,57,43,42,46,47,28,29,30,31,41,48,49,52,53,54,55,56,58,63,65,64,247199,247200,66)
)
AND node.showapproved > 0
AND node.viewperms > 1
AND node.showpublished > 0
)
)
OR starter.parentid = 9 AND node.userid IN (0)
)
)
ORDER BY node.lastcontent DESC,node.nodeid ASC
LIMIT 500
I'm trying to work around the "You can't specify target table for update in FROM clause" MySQL error, which means I've got a nested subquery (temp table). Note, I'm trying to get a SELECT to work before I move on to the actual UPDATE.
What I've got is a ledger table where I'm trying to find the associated row's calculated unit total using active_units (what the row started with) and with each additional adjustment in active units (there is one payment row and multiple adjustment rows in the same table that are associated by commission ID and schedule number). These are grouped by month_num. So if it's active_units = 18 and there are three adjustment rows, one with active_units_chg = -2, then I should end up with 18 + -2 = 16.
When I do this:
SELECT
active_units
, active_units_chg
, active_units_total
, CRM_commission_payments.active_units + (
SELECT SUM(active_units_chg)
FROM CRM_commission_payments AS cp
WHERE cp.CRM_commissions_item_id = CRM_commission_payments.CRM_commissions_item_id
AND cp.schedule_a_no = CRM_commission_payments.schedule_a_no
AND cp.month_num = CRM_commission_payments.month_num
AND cp.item_active = 1
) AS active_units_cal1
FROM CRM_commission_payments
WHERE CRM_commission_payments.payment_type = 'payment'
AND CRM_commission_payments.CRM_quotes_item_id = 2457
active_units_cal1 is correct for the row. However, when I do this with a nested JOIN'd subquery, I get NULL for active_units_calc.calc_chg:
SELECT
active_units
, active_units_chg
, active_units_total
, CRM_commission_payments.active_units + (
SELECT SUM(active_units_chg)
FROM CRM_commission_payments AS cp
WHERE cp.CRM_commissions_item_id = CRM_commission_payments.CRM_commissions_item_id
AND cp.schedule_a_no = CRM_commission_payments.schedule_a_no
AND cp.month_num = CRM_commission_payments.month_num
AND cp.item_active = 1
) AS active_units_cal1
, active_units_calc.calc_chg
FROM CRM_commission_payments
LEFT JOIN (
SELECT
source.calc_chg
, source.CRM_commissions_item_id
, source.schedule_a_no
, source.month_num
FROM CRM_commission_payments AS cp1
INNER JOIN (
SELECT
SUM(active_units_chg) AS calc_chg
, cp.CRM_commissions_item_id
, cp.schedule_a_no
, cp.month_num
FROM CRM_commission_payments AS cp
WHERE cp.item_active = 1
) AS source
WHERE source.CRM_commissions_item_id = cp1.CRM_commissions_item_id
AND source.schedule_a_no = cp1.schedule_a_no
AND source.month_num = cp1.month_num
) AS active_units_calc ON (
active_units_calc.CRM_commissions_item_id = CRM_commission_payments.CRM_commissions_item_id
AND active_units_calc.schedule_a_no = CRM_commission_payments.schedule_a_no
AND active_units_calc.month_num = CRM_commission_payments.month_num
)
WHERE CRM_commission_payments.payment_type = 'payment'
AND CRM_commission_payments.CRM_quotes_item_id = 2457
What am I doing wrong?
The below data shows time schedule having elective/ non-elective subjects of a student. My requirement is to select those rows when both elec and nonelec type has same period so in this case select elec type. Means for a day's schedule elective (type elec) should be given preference when both having same period. And when type elec does not has period like period 5 then select the non-elective one.
My Query
SELECT s.sch_id, s.sch_subtype, sd.sdetail_id, sd.sdetail_period
FROM schedule s
INNER JOIN schedule_detail sd ON s.sch_id = sd.sdetail_schedule
WHERE '2014-04-30'
BETWEEN sch_datefrom
AND sch_dateto
AND
(
(
sch_section =1
AND sch_subtype = 'nonelec'
)
OR
(
sch_subtype = 'elec'
AND 272
IN
(
SELECT edetail_stuid
FROM elective_detail
WHERE edetail_elective = sch_section
)
)
)
AND sch_course =3
AND sch_batch =2
AND sch_termid =2
AND sdetail_day = 'wed'
AND sdetail_period >0
AND CASE WHEN sch_subtype = 'nonelec'
THEN 1 =1
WHEN sch_subtype = 'elec'
THEN sdetail_subject >0
AND sdetail_faculty >0
AND sdetail_room >0
END GROUP BY CASE WHEN sch_subtype = 'elec'
THEN sdetail_period
ELSE 1
END ORDER BY sdetail_period
Output of above query
Required Output
You can try something of this sort :
SELECT sch_id,sch_subtype,sdetail_id,sdetail_period
FROM table
WHERE condition
group by sch_subtype
It would be better if you can post the query which u tried.
Dont really get whats the problem here:
SELECT * FROM schedule s
JOIN schedule_detail sd ON s.sch_id = sd.sdetail_schedule
LEFT JOIN elective_detail ed ON sd.sch_section = ed.edetail_elective
WHERE
(
sd.sch_section =1
AND s.sch_subtype = 'nonelec'
)
OR
(
ed.edetail_stuid = 227
AND sch_subtype = 'elec'
)
GROUP BY sd.sdetail_period
SQL Fiddle: http://sqlfiddle.com/#!2/69d4e/1
I'm currently coallescing fields individually in MySQL queries, but I would like to coalesce whole records.
Is this possible?
SELECT la.id,
COALESCE(( SELECT name FROM lookup_changed l0,
( SELECT MAX(id) id
FROM lookup_changed
WHERE lookup_id = 26
) l1
WHERE l0.id = l1.id
), la.name) name,
COALESCE(( SELECT msisdn FROM lookup_changed l0,
( SELECT MAX(id) id
FROM lookup_changed
WHERE lookup_id = 26
) l1
WHERE l0.id = l1.id
), la.msisdn) msisdn
FROM lookup_added la
WHERE la.id = 26
#Alma Do - the pseudo-SQL is:
SELECT la.id,
MULTICOALESCE(( SELECT <name, msisdn> FROM lookup_changed l0,
( SELECT MAX(id) id
FROM lookup_changed
WHERE lookup_id = 26
) l1
WHERE l0.id = l1.id
), <la.name, la.msisdn>) <name, msisdn>
FROM lookup_added la
WHERE la.id = 26
Since COALESCE() "return[s] the first non-NULL argument", it sounds like you want to retreive the "first non-NULL result from a set for queries":
-- syntax error
SELECT COALESCE(
SELECT a FROM ta,
SELECT b FROM tb
);
-- roughly equates to
( SELECT a AS val FROM ta WHERE a IS NOT NULL ORDER BY a LIMIT 1 )
UNION
( SELECT b AS val FROM tb WHERE b IS NOT NULL ORDER BY b LIMIT 1 )
ORDER BY val LIMIT 1 ;
Comments:
I added ORDER BY clauses, otherwise "first row" means nothing
the inner LIMIT 1 clauses are optional (but allow early trimming of sub-results)
the parenthesis around the sub queries are mandatory
Suppose equity has a column called TickerID. I would like to replace the 111's with equity.TickerID. MySQL can't seem to resolve the scope and returns an unknown column when I try that. This SQL statement works but I need to run it for each ticker. Would be nice if I could get a full table.
SELECT Ticker,
IF(tbl_m200.MA200_Count = 200,tbl_m200.MA200,-1) AS MA200,
IF(tbl_m50.MA50_Count = 50,tbl_m50.MA50,-1) AS MA50,
IF(tbl_m20.MA20_Count = 20,tbl_m20.MA20,-1) AS MA20
FROM equity
INNER JOIN
(SELECT TickerID,AVG(Y.Close) AS MA200,COUNT(Y.Close) AS MA200_Count FROM
(
SELECT Close,TickerID FROM equity_pricehistory_daily
WHERE TickerID = 111
ORDER BY Timestamp DESC LIMIT 0,200
) AS Y
) AS tbl_m200
USING(TickerID)
INNER JOIN
(SELECT TickerID,AVG(Y.Close) AS MA50,COUNT(Y.Close) AS MA50_Count FROM
(
SELECT Close,TickerID FROM equity_pricehistory_daily
WHERE TickerID = 111
ORDER BY Timestamp DESC LIMIT 50
) AS Y
) AS tbl_m50
USING(TickerID)
INNER JOIN
(SELECT TickerID,AVG(Y.Close) AS MA20,COUNT(Y.Close) AS MA20_Count FROM
(
SELECT Close,TickerID FROM equity_pricehistory_daily
WHERE TickerID = 111
ORDER BY Timestamp DESC LIMIT 0,20
) AS Y
) AS tbl_m20
USING(TickerID)
This seems to be some bug or "feature" of MySQL. Many persons seems to have the same problem with outer tables being out of scope.
Anyway... You could create functions that retrieve the information you want:
DROP FUNCTION IF EXISTS AveragePriceHistory_20;
CREATE FUNCTION AveragePriceHistory_20(MyTickerID INT)
RETURNS DECIMAL(9,2) DETERMINISTIC
RETURN (
SELECT AVG(Y.Close)
FROM (
SELECT Z.Close
FROM equity_pricehistory_daily Z
WHERE Z.TickerID = MyTickerID
ORDER BY Timestamp DESC
LIMIT 20
) Y
HAVING COUNT(*) = 20
);
SELECT
E.TickerID,
E.Ticker,
AveragePriceHistory_20(E.TickerID) AS MA20
FROM equity E;
You would get NULL instead of -1. If this is undesirable, you could wrap the function-call with IFNULL(...,-1).
Another way of solving this, would be to select for the time-frame, instead of using LIMIT.
SELECT
E.TickerID,
E.Ticker,
(
SELECT AVG(Y.Close)
FROM equity_pricehistory_daily Y
WHERE Y.TickerID = E.TickerID
AND Y.Timestamp > ADDDATE(CURRENT_TIMESTAMP, INTERVAL -20 DAY)
) AS MA20
FROM equity E;