Select the most recent row from a log table using timestamp - mysql

I have a table for logging a Facebook application user actions. I want to get the latest row that is not older then 9 minutes for a specific action ID. The table has a lot of columns of other statistical information, so I will show only 2 of the rows that represent the problem:
timestamp facebookID producerID eventID actionID numOfTickets
2012-05-28 13:16:38 100003286974944 9 1741 cpf 2
2012-05-28 13:16:13 100003286974944 9 1741 cpf 4
What I want to do is getting the latest row where actionID = 'cpf'.
What I've tried is:
SELECT CONCAT_WS(' ', y.firstName, y.lastName) as fullName, x.facebookID, x.numOfTickets, MAX(x.timestamp)
FROM E4S_ANALYTICS.e4s_analytic_data x INNER JOIN E4S_FB.e4s_user_details y ON x.facebookID = y.facebookID
WHERE (x.actionID = 'CPF' AND x.numOfTickets > 0 AND x.producerID = 9 AND TIMEDIFF(NOW() , x.timestamp) < '00:09:00'
AND x.facebookID IN (SELECT facebookID FROM E4S_FB.e4s_session_data WHERE
TIMEDIFF(NOW() , sessionStart) < '00:09:00' ))
The result of the query is:
facebookID numOfTickets MAX(x.timestamp)
100003286974944 4 2012-05-28 13:16:38
The timestamp returned is correct but the numOfTickets is 4 instead of 2.
For note, the inner query:
SELECT facebookID FROM E4S_FB.e4s_session_data
WHERE TIMEDIFF(NOW() , sessionStart) < '00:09:00' ))
Is used to see who is still logged in to the application.

SELECT CONCAT_WS(' ', y.firstName, y.lastName) AS fullName,
x.facebookID,
x.numOfTickets,
x.timestamp
FROM (
SELECT *
FROM E4S_ANALYTICS.e4s_analytic_data
WHERE actionID = 'cpf'
AND numOfTickets > 0
AND producerID = 9
AND TIMEDIFF(NOW() , timestamp) < '00:09:00'
AND (facebookID, timestamp) IN (
SELECT facebookID, MAX(timestamp)
FROM E4S_ANALYTICS.e4s_analytic_data
WHERE actionID = 'cpf'
AND numOfTickets > 0
AND producerID = 9
AND TIMEDIFF(NOW() , timestamp) < '00:09:00'
AND facebookID IN (
SELECT facebookID
FROM E4S_FB.e4s_session_data
WHERE TIMEDIFF(NOW() , sessionStart) < '00:09:00'
)
GROUP BY facebookID
)
) AS x
INNER JOIN E4S_FB.e4s_user_details AS y USING (facebookID)

you can use order by timestamp desc to order the column according to latest first and then select the first row.
or try using max.

Have you tried not using MAX()?
Assuming you've checked JOIN and SUBQUERY results.
SELECT CONCAT_WS(' ', y.firstName, y.lastName) as fullName, x.facebookID, x.numOfTickets, MAX(x.timestamp)
FROM E4S_ANALYTICS.e4s_analytic_data x
INNER JOIN E4S_FB.e4s_user_details y ON x.facebookID = y.facebookID
GROUP BY x.facebookID
WHERE (x.actionID = 'CPF' AND x.numOfTickets > 0 AND x.producerID = 9 AND TIMEDIFF(NOW() , x.timestamp) < '00:09:00'
AND x.facebookID IN
(SELECT facebookID FROM E4S_FB.e4s_session_data
WHERE TIMEDIFF(NOW() , sessionStart) < '00:09:00' ))
ORDER BY x.timestamp DESC;

Related

2 SELECT in a query with ORDER BY

I need to create a MYSQL query that will return the following:
excel
this is my query
SELECT t1.fecha_salida,
t1.agencia,
t2.fecha_salida,
t2.directa
FROM (SELECT fecha_salida, COUNT(*) AS agencia
FROM ventas
WHERE ventas.eliminado = 0 AND ventas.cliente_id !=2
GROUP BY fecha_salida) AS t1,
(SELECT fecha_salida, COUNT(*) AS directa
FROM ventas
WHERE ventas.eliminado = 0 AND ventas.cliente_id =2
GROUP BY fecha_salida) AS t2
GROUP BY t1.fecha_salida
my table is:
|------ |Columna|Tipo|Nulo|Predeterminado |------
|//**venta_id**//|int(11)|No| |usuario_id|int(11)|No|
|tour_id|int(11)|No| |cliente_id|int(11)|No| |vehiculo_id|int(11)|No|
|cashflow_id|int(11)|No| |total_compra|int(6)|No|
|total_pagado|int(6)|No| |total_iva|int(6)|No|
|total_comision|int(11)|No| |a_pagar|int(11)|No|
|fecha_venta|datetime|No| |fecha_salida|date|No|
|concretada|tinyint(1)|No| |pasajeros|int(3)|No|
|nombre|varchar(500)|Sí|NULL |direccion|varchar(500)|Sí|NULL
|observaciones|varchar(500)|Sí|NULL |forma_pago|tinyint(2)|No|
|eliminado|tinyint(1)|No|
Can you help me
You can use UNION to combine two queries that have same structure , also you should select from combined result and then order them
SELECT * FROM (
SELECT fecha_salida, COUNT(*) AS agencia
FROM ventas
WHERE `fecha_venta` between '2012-03-11 00:00:00' and '2019-08-30 23:59:00'
and ventas.eliminado = 0
AND ventas.cliente_id = 2
GROUP BY fecha_salida
UNION
SELECT fecha_salida, COUNT(*) AS agencia
FROM ventas
WHERE `fecha_venta` between '2012-03-11 00:00:00' and '2019-08-30 23:59:00'
and ventas.eliminado = 0
AND ventas.cliente_id != 2
GROUP BY fecha_salida
) RESULT
ORDER BY agencia

How to group by date

Below I cannot do Group by Date the following figures.
I have tried to put Group By in different lines, but not working.
SELECT SUM(a.NetAmount) AS TotalDonation
FROM (
SELECT
(
CASE WHEN bt.BalanceTransactionCurrencyID = 17
THEN bt.BalanceTransactionNet
ELSE
bt.BalanceTransactionNet * (SELECT TOP 1 ExrateValue FROM Exrate WHERE ExrateDate < bt.BalanceTransactionCreated AND bt.BalanceTransactionCurrencyID = CurrencyID ORDER BY ExrateDate Desc)
END
) AS NetAmount
FROM Charge as ch
JOIN BalanceTransaction as bt ON (ch.BalanceTransactionID = bt.BalanceTransactionID)
WHERE ch.ChargeCreatedDate BETWEEN '3-1-2019' AND '3-31-2019'
) AS a
I wanted to see:
Days Total Amount
March 1 xxxx
March 2 xxxx
March 3 xxx
MySQL does not use TOP. Use LIMIT:
SELECT ChargeCreatedDate, SUM(netamount)
FROM (SELECT ch.ChargeCreatedDate,
(CASE WHEN bt.BalanceTransactionCurrencyID = 17
THEN bt.BalanceTransactionNet
ELSE bt.BalanceTransactionNet * (SELECT e.ExrateValue
FROM Exrate e
WHERE e.ExrateDate < bt.BalanceTransactionCreated AND
e.CurrencyID = bt.BalanceTransactionCurrencyID
ORDER BY ExrateDate Desc
LIMIT 1
)
END) AS NetAmount
FROM Charge ch JOIN
BalanceTransaction bt
ON ch.BalanceTransactionID = bt.BalanceTransactionID
WHERE ch.ChargeCreatedDate BETWEEN '2019-03-01' AND '2019-03-31'
) chtbt
GROUP BY ChargeCreatedDate;
If you happen to be using SQL Server, you can replace the LIMIT 1 with FETCH FIRST 1 ROW ONLY.
The following code will hopefully display what you are looking for
SELECT a.Days AS Days, SUM(cast(a.NetAmount as decimal(16,9))) AS TotalDonation
FROM (
SELECT
(
CASE WHEN bt.BalanceTransactionCurrencyID = 17
THEN bt.BalanceTransactionNet
ELSE
bt.BalanceTransactionNet * (SELECT TOP 1 ExrateValue FROM Exrate WHERE ExrateDate < bt.BalanceTransactionCreated AND bt.BalanceTransactionCurrencyID = CurrencyID ORDER BY ExrateDate Desc)
END
) AS NetAmount,
ch.ChargeCreatedDate as Days
FROM Charge as ch
JOIN BalanceTransaction as bt ON (ch.BalanceTransactionID = bt.BalanceTransactionID)
WHERE ch.ChargeCreatedDate BETWEEN '3-1-2019' AND '3-31-2019'
) AS a GROUP BY a.Days
This should be sufficient. You need to SELECT the desired value in the query in order to get it to show up. Also when using the SUM() function you need to specify what the group value will be.

Select multiple columns by date, count occurrence for each column

I am trying to get this query...
SELECT `Num_1`, COUNT(`Num_1`) AS `value_occurrence` FROM numbers WHERE MONTH(`Dates`) = 1 AND YEAR(`Dates`) = 1995 GROUP BY `Num_1` ORDER BY `value_occurrence` DESC
But for multiple columns as in 'Num_1', 'Num_2', 'Num_3', 'Num_4', 'Num_5' and return with the occurrence of each column such as 'num_1_occurrence', 'num_2_occurrence', 'num_3_occurrence', 'num_4_occurrence', 'num_5_occurrence' and all within the date specified.
numbers table
Example output
I had tried using...
SELECT `Num_1`,`Num_2`, `Num_3`,`Num_4`,`Num_5`,COUNT(`Num_1`,`Num_2`,`Num_3`,`Num_4`,`Num_5`) AS `num_1_occurrence`,`num_2_occurrence`,`num_3_occurrence`, `num_4_occurrence`,`num_5_occurrence`FROM numbers WHERE MONTH(`Dates`) = 1 AND YEAR(`Dates`) = 1995
but just threw errors, I have searched extensively for days and have not found the correct way to do it.
I'd do it like this:
SELECT n.num
, MAX(IF(n.q='n1',n.cnt,NULL)) AS num_1_occurrence
, MAX(IF(n.q='n2',n.cnt,NULL)) AS num_2_occurrence
, MAX(IF(n.q='n3',n.cnt,NULL)) AS num_3_occurrence
FROM (
SELECT 'n1' AS q
, n1.Num_1 AS num
, COUNT(n1.Num_1) AS cnt
FROM numbers n1
WHERE n1.Dates >= '1995-01-01'
AND n1.Dates < '1995-01-01' + INTERVAL 1 MONTH
GROUP BY n1.Num_1
UNION ALL
SELECT 'n2' AS q
, n2.Num_2 AS num
, COUNT(n2.Num_2) AS cnt
FROM numbers n2
WHERE n2.Dates >= '1995-01-01'
AND n2.Dates < '1995-01-01' + INTERVAL 1 MONTH
GROUP BY n2.Num_2
UNION ALL
SELECT 'n3' AS q
, n3.Num_3 AS num
, COUNT(n3.Num_3) AS cnt
FROM numbers n3
WHERE n3.Dates >= '1995-01-01'
AND n3.Dates < '1995-01-01' + INTERVAL 1 MONTH
GROUP BY n3.Num_3
) n
GROUP BY n.num
ORDER BY GREATEST(num_1_occurrence,num_2_occurrence,num_3_occurrence) DESC
I'm only doing Num_1 and Num_2 here, but I think it's what you're looking for, or close. This will give you the list in "tall" format, with the original column name, the value in that column, and the count of that value in that column going across...
SELECT 'Num_1' AS field_name, Num_1 AS value, value_count
FROM (SELECT Num_1, COUNT(Num_1) AS value_count
FROM numbers
GROUP BY Num_1) AS num1_counts
WHERE MONTH(`Dates`) = 1 AND YEAR(`Dates`) = 1995
UNION
SELECT 'Num_2' AS field_name, Num_2 AS value, value_count
FROM (SELECT Num_2, COUNT(Num_2) AS value_count
FROM numbers
GROUP BY Num_2) AS num2_counts
WHERE MONTH(`Dates`) = 1 AND YEAR(`Dates`) = 1995

tsql best way to merge records with start date and end date when there is no gap in between

I have a mapping table as follows :
FirstEntityID int
MappedTo int
BeginDate Date
EndDate Date
and lets say I have following records in the table :
FirstEntityID MappedTo BeginDate EndDate
1 2 2012-09-01 2012-10-01
2 3 2012-09-01 2012-10-01
1 2 2012-10-02 2012-11-24
2 3 2012-11-01 2012-11-24
I need a script which will get this table and merges records based on the Start and end date to return a result like :
FirstEntityID MappedTo BeginDate EndDate
1 2 2012-09-01 2012-11-24
2 3 2012-09-01 2012-10-01
2 3 2012-11-01 2012-11-24
Using CTEs, we find the starting dates first:
; WITH StartD AS
( SELECT
FirstEntityID
, MappedTo
, BeginDate
, ROW_NUMBER() OVER( PARTITION BY FirstEntityID, MappedTo
ORDER BY BeginDate )
AS Rn
FROM
tableX AS t
WHERE
NOT EXISTS
( SELECT *
FROM tableX AS p
WHERE p.FirstEntityID = t.FirstEntityID
AND p.MappedTo = t.MappedTo
AND p.BeginDate < t.BeginDate
AND t.BeginDate <= DATEADD(day, 1, p.EndDate)
)
)
then the ending dates:
, EndD AS
( SELECT
FirstEntityID
, MappedTo
, EndDate
, ROW_NUMBER() OVER( PARTITION BY FirstEntityID, MappedTo
ORDER BY EndDate )
AS Rn
FROM
tableX AS t
WHERE
NOT EXISTS
( SELECT *
FROM tableX AS p
WHERE p.FirstEntityID = t.FirstEntityID
AND p.MappedTo = t.MappedTo
AND DATEADD(day, -1, p.BeginDate) <= t.EndDate
AND t.EndDate < p.EndDate
)
)
and the final result:
SELECT
s.FirstEntityID
, s.MappedTo
, s.BeginDate
, e.EndDate
FROM
StartD AS s
JOIN
EndD AS e
ON e.FirstEntityID = s.FirstEntityID
AND e.MappedTo = s.MappedTo
AND e.Rn = s.Rn ;
Tested in SQL-Fiddle
Tested this and it seems to work
It will fail on an edge case with duplicate rows.
For that would need to go with a RowNumber approach like Ypercube.
Or add a constraint on the table to force the row to be unique.
-- first the overlaps
SELECT T1.FirstEntityId, T1.MappedTo, T1.BeginDate, Max(T2.EndDate) as [EndDate]
FROM tablex as T1
join tablex as T2
on T1.FirstEntityId = T2.FirstEntityId
and T1.MappedTo = T2.MappedTo
and T1.EndDate >= T2.BeginDate
and T1.EndDate < T2.EndDate
and T1.BeginDate <= T2.BeginDate
GROUP BY T1.FirstEntityId, T1.MappedTo, T1.BeginDate
union
-- add the non overlaps
SELECT T1.FirstEntityId, T1.MappedTo, T1.BeginDate, T1.EndDate
FROM tablex as T1
join tablex as T2
on T1.FirstEntityId = T2.FirstEntityId
and T1.MappedTo = T2.MappedTo
and ( T1.EndDate < T2.BeginDate or T1.BeginDate > T2.EndDate
or (T1.BeginDate < T2.BeginDate and T1.EndDate > T2.EndDate) )
order by FirstEntityId, MappedTo, BeginDate
This might work:
SELECT FirstEntityId, MappedTo, Min(BeginDate), Max(EndDate)
FROM
T1
GROUP BY
FirstEntityId, MappedTo

JIRA : Issue status count for the past x (i.e 30 ) days

With below Query I able to see the count(no) of issues for all issueType in JIRA for a given date .
ie.
SELECT count(*), STEP.STEP_ID
FROM (SELECT STEP_ID, ENTRY_ID
FROM OS_CURRENTSTEP
WHERE OS_CURRENTSTEP.START_DATE < '<your date>'
UNION SELECT STEP_ID, ENTRY_ID
FROM OS_HISTORYSTEP
WHERE OS_HISTORYSTEP.START_DATE < '<your date>'
AND OS_HISTORYSTEP.FINISH_DATE > '<your date>' ) As STEP,
(SELECT changeitem.OLDVALUE AS VAL, changegroup.ISSUEID AS ISSID
FROM changegroup, changeitem
WHERE changeitem.FIELD = 'Workflow'
AND changeitem.GROUPID = changegroup.ID
UNION SELECT jiraissue.WORKFLOW_ID AS VAL, jiraissue.id as ISSID
FROM jiraissue) As VALID,
jiraissue as JI
WHERE STEP.ENTRY_ID = VALID.VAL
AND VALID.ISSID = JI.id
AND JI.project = <proj_id>
Group By STEP.STEP_ID;
the result is
Status Count
open 12
closed 13
..... ....
What I'd like to achieve is something like this actually ..where the total count for status open and closed for each day .
Date COUNT(Open) COUNT(Closed)
12-1-2012 12 1
13-1-2012 14 5
The general strategy would be this:
Select from a table of all the days in a month
LEFT OUTER JOIN your table that gets counts for each day
(left outer join being necessary in case there were no entries for that day, you'd want it to show a zero value).
So I think this is roughly what you need (not complete and date-function syntax is probably wrong for your db, but it will get you closer):
SELECT aDate
, COALESCE(SUM(CASE WHEN IssueStatus = 'whateverMeansOpen' THEN 1 END,0)) OpenCount
, COALESCE(SUM(CASE WHEN IssueStatus = 'whateverMeansClosed' THEN 1 END,0)) ClosedCount
FROM
(
SELECT DATEADD(DAY, I, #START_DATE) aDate
FROM
(
SELECT number AS I FROM [SomeTableWithAtLeast31Rows]
where number between 1 and 31
) Numbers
WHERE DATEADD(DAY, I, #START_DATE) < #END_DATE
) DateTimesInInterval
LEFT OUTER JOIN
(
Put your query here. It needs to output two columns, DateTimeOfIssue and IssueStatus
) yourHugeQuery ON yourHugeQuery.DateTimeOfIssue BETWEEN aDate and DATEADD(DAY, 1, aDate)
GROUP BY aDate
ORDER BY aDate