Unique value per day - mysql

i am looking how to have unique value per day, here an exemple:
CREATE TABLE IF NOT EXISTS calls (
id int(11) default NULL,
calldate datetime default NULL,
dst varchar(80) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO calls (id, calldate, dst) VALUES
(1, '2014-05-03 20:45:43', '22561037352'),
(2, '2014-05-04 20:07:49', '22561037352'),
(3, '2014-05-04 13:16:14', '22561037352'),
(4, '2014-05-04 20:08:58', '22560991034'),
(5, '2014-05-04 16:06:02', '22560991034'),
(6, '2014-05-04 20:22:19', '22560842218');
sqlfiddle: Copy and paste to test
we have two number coming two times per day 22561037352 & 22560991034, i want to show unique number per day.

http://sqlfiddle.com/#!9/84076/11
SELECT DISTINCT DATE_FORMAT (calldate,'%Y-%m-%d') calldate, dst
FROM calls

SELECT DISTINCT t.*
FROM (SELECT DATE (calldate) as calldate, dst FROM calls) t

First call to the number for the day
SELECT *
FROM calls c
WHERE NOT EXISTS (SELECT 'a'
FROM calls c2
WHERE c2.dst = c.dst
AND DATE_FORMAT(c2.calldate,'%d/%m/%Y') = DATE_FORMAT(c.calldate,'%d/%m/%Y')
AND c2.calldate < c.calldate
)

Related

(SQL) how to get the number of the entry in the queue?

I have this table:
CREATE TABLE tickets (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
topic VARCHAR(64) NOT NULL,
priority TINYINT NOT NULL default 1,
created DATETIME);
INSERT INTO tickets (id, topic, priority, created) VALUES
(1, 'kin23oi5n2', 3, '2018-05-27 16:00:54'),
(2, 'ewbrv32b3', 2, '2018-05-27 16:00:54'),
(3, 'aern23523', 1, '2018-05-27 16:01:15'),
(4, '4bt43t3', 5, '2018-05-27 16:01:15'),
(5, '32n523n5235n235t3n4', 4, '2018-05-27 16:01:39'),
(6, 'e2nr2n23n5235n23n523', 3, '2018-05-27 16:01:39');
I'm running a query:
SELECT * FROM `tickets` order by `priority` ASC, `created` desc;
How do I get the row number with id 5 in this result using sql?
update:
SELECT count(*) as pos FROMticketsWHERE ...;
As a result, we obtain pos
I try to make that my result was similar to this but contained number of a line of the necessary row(id 5 for example).
in other words I want to get the number of the queue entry
If someone is interested, here is the answer
SELECT num FROM
(SET #row_number = 0;
SELECT
(#row_number:=#row_number + 1) AS num, id
FROM
tickets order by `priority` ASC, `created` desc) as tmp_table WHERE id = 6;
But now there was another question. How is this implemented in Larabel 5.6?
UP
And he did it.

MySQL COUNT(*) not counting result rows

Simplified schema of m:n relation implementing a subscription model:
CREATE TABLE c (
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(32)
) ENGINE=MyISAM CHARACTER SET=UTF8;
CREATE TABLE t (
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(32)
) ENGINE=MyISAM CHARACTER SET=UTF8;
CREATE TABLE c2t (
id INT(11) PRIMARY KEY AUTO_INCREMENT,
cid INT(11) NOT NULL,
tid INT(11) NOT NULL,
dateStart DATE NULL,
dateEnd DATE NULL
) ENGINE=MyISAM CHARACTER SET=UTF8;
INSERT INTO c (name) VALUES ('mike'),('carl'),('suzy');
INSERT INTO t (name) VALUES ('plan1'),('plan2'),('plan3'),('plan4');
INSERT INTO c2t (cid, tid, dateStart, dateEnd) VALUES
(1, 1, '2014-01-01', '2014-07-31'),
(1, 2, '2014-08-01', '2015-07-31'),
(1, 1, '2015-08-01', null),
(1, 3, '2015-09-01', null),
(2, 1, '2014-01-01', '2015-07-31'),
(2, 2, '2015-08-01', '2015-09-30'),
(2, 3, '2015-09-30', null),
(3, 1, '2014-01-01', '2014-12-31'),
(3, 2, '2014-01-01', '2014-12-31'),
(3, 3, '2015-01-01', '2015-10-31'),
(3, 4, '2015-01-01', '2015-10-31');
I've developed a query to find the c's who have active subscriptions of t's:
SELECT c.*
FROM c
LEFT JOIN c2t ON c.id = c2t.cid
AND NOW() BETWEEN COALESCE(dateStart, '0000-00-00')
AND COALESCE(dateEnd, DATE_ADD(NOW(), INTERVAL 1 DAY))
GROUP BY c2t.cid
HAVING COUNT(c2t.id) > 0;
Result as expected:
id name
1 mike
2 carl
The problem arises when I try to count the result rows. The query is almost identical, I've just dropped in a COUNT(*):
SELECT COUNT(*)
FROM c
LEFT JOIN c2t ON c.id = c2t.cid
AND NOW() BETWEEN COALESCE(dateStart, '0000-00-00')
AND COALESCE(dateEnd, DATE_ADD(NOW(), INTERVAL 1 DAY))
GROUP BY c2t.cid
HAVING COUNT(c2t.id) > 0;
Result:
`COUNT(*)`
2
1
Expected result would be a single row containing the number of rows found (2). I can only assume that the GROUP BY is interfering, but have no idea how to work around. Explanations are most welcome.
Wrap everything with subquery and use COUNT in outer query:
SELECT COUNT(*)
FROM (
SELECT c.*
FROM c
LEFT JOIN c2t ON c.id = c2t.cid
AND NOW() BETWEEN COALESCE(dateStart, '0000-00-00')
AND COALESCE(dateEnd, DATE_ADD(NOW(), INTERVAL 1 DAY))
GROUP BY c2t.cid
HAVING COUNT(c2t.id) > 0
) AS sub
If the only thing you want returned is the number of c's who have active subscriptions, then you can simplify your query like this:
SELECT COUNT(DISTINCT c.id) AS cnt
FROM c
INNER JOIN c2t ON c.id = c2t.cid
AND NOW() BETWEEN COALESCE(dateStart, '0000-00-00')
AND COALESCE(dateEnd, DATE_ADD(NOW(), INTERVAL 1 DAY))
So, INNER JOIN is used in place of LEFT JOIN: there is no need to return c's with no matches in c2t, since these are not going to have any active subscriptions.
Also, there is no need to GROUP BY: the query returns just one row with the number of c's.
Finally, DISTINCT must be used in COUNT so as to avoid counting duplicate c.id values more than once.

Count results for the current date using fields of type datetime

I am trying to count the entries for the current day and sum the total. Currently, I have a query that counts the entries per day. I am using the datetime field to achieve my end goal. What would be the best approach to count the entries for the current day and sum the total?
CREATE TABLE product_entry
(`id` int, `entry_time` datetime, `product` varchar(55))
;
INSERT INTO product_entry
(`id`, `entry_time`, `product`)
VALUES
(1, '2015-09-03 15:16:52', 'dud1'),
(2, '2015-09-03 15:25:00', 'dud2'),
(3, '2015-09-04 16:00:12', 'dud3'),
(4, '2015-09-04 17:23:29', 'dud4')
;
SQLFIDDLE
Query
SELECT entry_time, count(*)
FROM product_entry
GROUP BY hour( entry_time ) , day( entry_time )
Schema
CREATE TABLE product_entry
(`id` int, `entry_time` datetime, `product` varchar(55))
;
INSERT INTO product_entry
(`id`, `entry_time`, `product`)
VALUES
(1, '2015-09-03 15:16:52', 'dud1'),
(2, '2015-09-03 15:25:00', 'dud2'),
(3, '2015-09-04 16:00:12', 'dud3'),
(4, '2015-09-04 17:23:29', 'dud4')
;
The title of your question says Count results for the current date ..., but the query you have tried suggests you want to show result counts for every distinct date. I am not sure which one you need. If the former is the case, you could simply use:
SELECT COUNT(`id`) FROM `product_entry` WHERE DATE(`entry_time`) = CURDATE()
To get count for today:
SELECT COUNT(`id`) FROM `product_entry` WHERE DATE(`entry_time`) = CURRENT_DATE
To get count for yesterday (needed when You want to get entries at end of the day):
SELECT COUNT(`id`) FROM `product_entry` WHERE DATE(`entry_time`) = SUBDATE(CURRENT_DATE, 1)
For all time grouped by date and formated:
SELECT DATE_FORMAT(entry_time,'%Y-%m-%d'), count(*)
FROM product_entry
GROUP BY date(entry_time)
this is MSSQL Code maybe your help
SELECT day([product_entry].[entry_time])as input, count(*) as Miktar
FROM [product_entry]
GROUP BY day([entry_time])

How to optmize query with a query with multiple GROUP BY's,sub queries and WHERE IN over a large table?

I am working on a scraping project to crawl items and their scores over different schedules.Schedule is a user defined period (date) when the script is intended to run.
Table structure is as follows:
--
-- Table structure for table `test_join`
--
CREATE TABLE IF NOT EXISTS `test_join` (
`schedule_id` int(11) NOT NULL,
`player_name` varchar(50) NOT NULL,
`type` enum('celebrity','sportsperson') NOT NULL,
`score` int(11) NOT NULL,
PRIMARY KEY (`schedule_id`,`player_name`,`type`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Dumping data for table `test_join`
--
INSERT INTO `test_join` (`schedule_id`, `player_name`, `type`, `score`) VALUES
(1, 'sachin', 'sportsperson', 100),
(1, 'ganguly', 'sportsperson', 80),
(1, 'dravid', 'sportsperson', 60),
(1, 'sachin', 'celebrity', 100),
(2, 'sachin', 'sportsperson', 120),
(2, 'ganguly', 'sportsperson', 100),
(2, 'sachin', 'celebrity', 120);
The scraping is done over periods and for each schedule it is expected to have about 10k+ entries.The schedules could be made in daily basis,hence the data would grow to be be around 2 million in 5-6 months.
Over this data I need to perform queries to aggregate the player who come across each schedules in a selected range of schedules.
For example:
I need aggregate same players who come across multiple schedules. If schedule 1 and 2 are selected,items which come under both of the schedules only will be selected.
I am using the following query to aggregate results based on the type,
For schedule 1:
SELECT fullt.type,COUNT(*) as count,SUM(fullt.score) FROM
(SELECT tj.*
FROM `test_join` tj
RIGHT JOIN
(SELECT `player_name`,`type`,COUNT(`schedule_id`) as c FROM `test_join` WHERE `schedule_id` IN (1,2) GROUP BY `player_name`,`type` HAVING c=2) stj
on tj.player_name = stj.player_name
WHERE tj.`schedule_id`=1
GROUP BY tj.`type`,tj.`player_name`)AS fullt
GROUP BY fullt.type
Reason for c = 2;
WHERE `schedule_id` IN (1,2) GROUP BY `player_name`,`type` HAVING c=2
Here we are selecting two schedules,1 and 2.Hence the count 2 is taken to make the query to to fetch records which belongs to both the schedules and occurs twice.
It would generate a results as follows,
Schedule 1 :Expected Results
Schedule 2 :Expected Results
This is my expected result and the query returns the results as above.
(In the real case I have to work across pretty big MySQL tables)
On my understanding of standardized MySQL queries, using sub queries,WHERE IN, varchar comparison fields ,multiple GROUP BY's would affect in the query performance.
I need the aggregate results in real time and query speed and well as standards are a concern too.How this could be optimized for better performance in this context.
EDIT:
I had reduced sub queries now:
SELECT fullt.type,COUNT(*) as count,SUM(fullt.score) FROM (
SELECT t.*
FROM `test_join` t
INNER JOIN test_join t1 ON t.`player_name` = t1.player_name AND t1.schedule_id = 1
INNER JOIN test_join t2 ON t.player_name = t2.player_name AND t2.schedule_id = 2
WHERE t.schedule_id = 2
GROUP BY t.`player_name`,t.`type`) AS fullt
GROUP BY fullt.type
Is this a better way to do so.I had replaced WHERE IN with JOINS.
Any advise would be highly appreciated.I would be happy to provide any supporting information if needed.
try below SQL Query in MYSQL:
SELECT tj.`type`,COUNT(*) as count,SUM(tj.`score`) FROM
`test_join` tj
where tj.`schedule_id`=1
and `player_name` in
(
select tj1.`player_name` from `test_join` tj1
group by tj1.`player_name` having count(tj1.`player_name`) > 1
)
group by tj.`type`
Actuallly I tried same data in Sybase as i dont have MySQL installed in my machine.It worked as exepected !
CREATE TABLE #test_join
(
schedule_id int NOT NULL,
player_name varchar(50) NOT NULL,
type1 varchar(15) NOT NULL,
score int NOT NULL,
)
INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES
(1, 'sachin', 'sportsperson', 100)
INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES(1, 'ganguly', 'sportsperson', 80)
INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES(1, 'dravid', 'sportsperson', 60)
INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES(1, 'sachin', 'celebrity', 100)
INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES(2, 'sachin', 'sportsperson', 120)
INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES(2, 'ganguly', 'sportsperson', 100)
INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES(2, 'sachin', 'celebrity', 120)
select * from #test_join
Print 'Solution #1 : Inner join'
select type1,count(*),sum(score) from
#test_join
where schedule_id=1 and player_name in (select player_name from #test_join t1 group by player_name having count(player_name) > 1 )
group by type1
select player_name,type1,sum(score) Score into #test_join_temp
from #test_join
group by player_name,type1
having count(player_name) > 1
Print 'Solution #2 using Temp Table'
--select * from #test_join_temp
select type1,count(*),sum(score) from
#test_join
where schedule_id=1 and player_name in (select player_name from #test_join_temp )
group by type1
I hope This Helps :)

time difference between two similar values

I want to find the time difference between two function names in my database. the database looks like this:
what I want to do is to find the time difference between two consecutive function names who have the same name. for example the output will be for "getPrice" at row number "2" and row number "3" and then time difference for "getPrice"at row "3" and row "5" and so on for all other times and all other function names. Please help me and thanks a lot!
I tried
SELECT a.lid, a.date, (b.date-a.date) as timeDifference
FROM myTable a
INNER JOIN myTable b ON b.lid = (a.lid+1)
ORDER BY a.lid ASC;
The problem is, it gives time difference for any consecutive function names even if they are not identical!
#tombom
there is a table I use for testing and have different variable names than the example I provided earlier. the table looks like this:
and after applying your code (and of course change the variable names to match with this table) the output looks like this:
as you can see the "getTax" is subtracted from "getPrice" although they are different. how can I solve this problem?? Thanks a lot.
the schema I'm trying to build is:
CREATE TABLE `test` (
`id` INT NOT NULL AUTO_INCREMENT ,
`nserviceName` VARCHAR(45) NULL ,
`functionName` VARCHAR(45) NULL ,
`time` TIMESTAMP NULL ,
`tps` INT NULL ,
`clientID` INT NULL ,
PRIMARY KEY (`id`) );
and the insert is :
INSERT INTO `test` (`id`, `nserviceName`, `functionName`, `time`, `tps`, `clientID`) VALUES ('1', 'X1', 'getPrice', '2013-05-23 00:36:08', '22', '0');
INSERT INTO `test` (`id`, `nserviceName`, `functionName`, `time`, `tps`, `clientID`) VALUES ('2', 'X2', 'getTax', '2013-05-23 00:38:00', '33', '0');
INSERT INTO `test` (`id`, `nserviceName`, `functionName`, `time`, `tps`, `clientID`) VALUES ('3', 'X1', 'getPrice', '2013-05-23 00:35:00', '12', '0');
INSERT INTO `test` (`id`, `nserviceName`, `functionName`, `time`, `tps`, `clientID`) VALUES ('4', 'X1', 'getPrice', '2013-05-23 00:35:00', '11', '0');
INSERT INTO `test` (`id`, `nserviceName`, `functionName`, `time`, `tps`, `clientID`) VALUES ('5', 'X2', 'getTax', '2013-05-23 00:35:00', '88', '0');
INSERT INTO `test` (`id`, `nserviceName`, `functionName`, `time`, `tps`, `clientID`) VALUES ('6', 'X1', 'getPrice', '2013-05-23 00:35:00', '33', '0');
thanks.
#tombom
the operation I want to perform on the table is like the following image:
where I start from the first record X1 getPrice which have no record before it. so no operation is required. then check number two getTax have no getPrice before it which are not identical so again no operation will be performed. then number 3 getPrice have getTax before it so it ignores it and check above getTax to find getPrice here it will do the time difference between getPrice(#3) and getPrice(#1). next getPrice at row 4 will check the rows above it, and it find the one directly above it is getPrice so time difference between getPrice*(#4) and getPrice(#3) will be found. then getTax at row 5 will check the rows above it until it finds a similar functionName (getTax) which is at row #2. then the time difference between getTax at row 5 and getTax at row 2 will be found.
thanks a lot..
Please have a try with this one:
SELECT lid, `date`, serviceName, functionName, responseTime, sid, timeDifference FROM (
SELECT
IF(#prevFname = functionName, SEC_TO_TIME(TIMESTAMPDIFF(SECOND, `date`, #prevDate)), 'functionName differs') AS timeDifference,
#prevFname := functionName AS a,
#prevDate := `date` AS b,
yt.*
FROM
yourTable yt
, (SELECT #prevFname:=NULL, #prevDate:=NULL) vars
ORDER BY functionName, `date`
) subquery_alias
I like to use user defined variables in such cases as I made amazing experiences regarding performance, since no self-join is needed.
Also note that I used the timestampdiff function and sec_to_time to polish the output. Timestampdiff is the correct way to subtract different dates(+times). Only downside is, that sec_to_time only allows a range from '00:00:00' to '23:59:59'. If this can lead to problems, remove the function again. Read more about both functions on this site.
UPDATE (less complicated than necessary):
SELECT lid, `date`, serviceName, functionName, responseTime, sid, timeDifference FROM (
SELECT
SEC_TO_TIME(TIMESTAMPDIFF(SECOND, #prevDate, `date`)) AS timeDifference,
#prevDate := `date` AS b,
yt.*
FROM
yourTable yt
, (SELECT #prevDate:=NULL) vars
ORDER BY lid
) subquery_alias
UPDATE 2:
This one resets the timedifference to 00:00:00 when functionName differs to previous one.
SELECT * /*choose here only the columns you need*/ FROM (
SELECT
IF(#prevFunction = functionName, SEC_TO_TIME(TIMESTAMPDIFF(SECOND, #prevDate, `time`)), '00:00:00') AS timeDifference,
#prevFunction := functionName AS a,
#prevDate := `time` AS b,
yt.*
FROM
test yt
, (SELECT #prevDate:=NULL, #prevFunction:=NULL) vars
ORDER BY id
) subquery_alias
UPDATE 3:
Okay, what a difficult birth. Just a minor tweak.
SELECT * /*choose here only the columns you need*/ FROM (
SELECT
IF(#prevFunction = functionName, SEC_TO_TIME(TIMESTAMPDIFF(SECOND, #prevDate, `time`)), '00:00:00') AS timeDifference,
#prevFunction := functionName AS a,
#prevDate := `time` AS b,
yt.*
FROM
test yt
, (SELECT #prevDate:=NULL, #prevFunction:=NULL) vars
ORDER BY functionName, id#, `time`
) subquery_alias
ORDER BY id
I order by function name and id again (or time if you prefer) in the subquery, do all the calculations, then sort it by id again in the outer query. That's it.