Mysql group by and count attempts on seperate column - php

I have a mySQL query that groups results by quiz attempt ID:
SELECT *
FROM quiz_log
WHERE archived = 0
GROUP BY quiz_attempt_id
ORDER BY quiz_attempt_id ASC
My question is how do I now count up the attempts in the by app_user_id. The app_user_id = 150 appears three times, so I need another column with the number 1 on the first line, 2 on the 3rd line and 3 on the 19th line.

You can use a correlated query:
SELECT t.*,
(SELECT count(distinct s.quiz_attempt_id) FROM quiz_log s
WHERE s.app_user_id = t.app_user_id
AND s.timestamp <= t.timestamp) as Your_Cnt
FROM quiz_log t
WHERE ....

Related

How select next row pagination in sql

I'm sorry I'm weak for English.
i echo 2 row in each page . how echo next 2 row
SELECT *
FROM `mzmx_post`
JOIN mzmx_post_category
WHERE mzmx_post.id = mzmx_post_category.post_id AND zmx_post_category.category_id = 5
ORDER BY id DESC
LIMIT 2
You can use the two-arguments form of LIMIT to offset the result by a given number of rows, like:
SELECT *
FROM `mzmx_post`
JOIN mzmx_post_category ON mzmx_post.id = mzmx_post_category.post_id
WHERE mzmx_post_category.category_id = 5
ORDER BY id DESC
LIMIT 2, 2 -- fetch records 3 and 4
This gives you the second page. If you want the third page, then:
LIMIT 4, 2
And so on.
Note that I modified your query so the joining condition between the tables is placed in the ON clause of the join rather than in the WHERE clause.
Better add one extra column (e.g. mzmx_post_key bigint) of Long type in each table and have sequential value on that column. Use that column to fetch data from DB from page wise.
sqL suery should look like:
SELECT *
FROM `mzmx_post`
JOIN mzmx_post_category ON mzmx_post.id = mzmx_post_category.post_id
WHERE mzmx_post_category.category_id = 5 and mzmx_post_key> ##last record key##
ORDER BY mzmx_post_key ASC
LIMIT 2
The basic idea is to use
LIMIT n,o
where n is the results per page
o is the offset from the first result
for the p-th page the offset would be
o = p * n
where p = 0,1,2,....

PHP MYSQL General Error returned when using LIMIT [duplicate]

This question already has answers here:
Implement paging (skip / take) functionality with this query
(6 answers)
Closed 1 year ago.
I have this query with MySQL:
select * from table1 LIMIT 10,20
How can I do this with SQL Server?
Starting SQL SERVER 2005, you can do this...
USE AdventureWorks;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
FROM Sales.SalesOrderHeader
)
SELECT *
FROM OrderedOrders
WHERE RowNumber BETWEEN 10 AND 20;
or something like this for 2000 and below versions...
SELECT TOP 10 * FROM (SELECT TOP 20 FROM Table ORDER BY Id) ORDER BY Id DESC
Starting with SQL SERVER 2012, you can use the OFFSET FETCH Clause:
USE AdventureWorks;
GO
SELECT SalesOrderID, OrderDate
FROM Sales.SalesOrderHeader
ORDER BY SalesOrderID
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
GO
http://msdn.microsoft.com/en-us/library/ms188385(v=sql.110).aspx
This may not work correctly when the order by is not unique.
If the query is modified to ORDER BY OrderDate, the result set returned is not as expected.
This is how I limit the results in MS SQL Server 2012:
SELECT *
FROM table1
ORDER BY columnName
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
NOTE: OFFSET can only be used with or in tandem to ORDER BY.
To explain the code line OFFSET xx ROWS FETCH NEXT yy ROW ONLY
The xx is the record/row number you want to start pulling from in the table, i.e: If there are 40 records in table 1, the code above will start pulling from row 10.
The yy is the number of records/rows you want to pull from the table.
To build on the previous example: If table 1 has 40 records and you began pulling from row 10 and grab the NEXT set of 10 (yy).
That would mean, the code above will pull the records from table 1 starting at row 10 and ending at 20. Thus pulling rows 10 - 20.
Check out the link for more info on OFFSET
This is almost a duplicate of a question I asked in October:
Emulate MySQL LIMIT clause in Microsoft SQL Server 2000
If you're using Microsoft SQL Server 2000, there is no good solution. Most people have to resort to capturing the result of the query in a temporary table with a IDENTITY primary key. Then query against the primary key column using a BETWEEN condition.
If you're using Microsoft SQL Server 2005 or later, you have a ROW_NUMBER() function, so you can get the same result but avoid the temporary table.
SELECT t1.*
FROM (
SELECT ROW_NUMBER OVER(ORDER BY id) AS row, t1.*
FROM ( ...original SQL query... ) t1
) t2
WHERE t2.row BETWEEN #offset+1 AND #offset+#count;
You can also write this as a common table expression as shown in #Leon Tayson's answer.
SELECT *
FROM (
SELECT TOP 20
t.*, ROW_NUMBER() OVER (ORDER BY field1) AS rn
FROM table1 t
ORDER BY
field1
) t
WHERE rn > 10
Syntactically MySQL LIMIT query is something like this:
SELECT * FROM table LIMIT OFFSET, ROW_COUNT
This can be translated into Microsoft SQL Server like
SELECT * FROM
(
SELECT TOP #{OFFSET+ROW_COUNT} *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum
FROM table
) a
WHERE rnum > OFFSET
Now your query select * from table1 LIMIT 10,20 will be like this:
SELECT * FROM
(
SELECT TOP 30 *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum
FROM table1
) a
WHERE rnum > 10
SELECT TOP 10 * FROM table;
Is the same as
SELECT * FROM table LIMIT 0,10;
Here's an article about implementing Limit in MsSQL Its a nice read, specially the comments.
This is one of the reasons I try to avoid using MS Server... but anyway. Sometimes you just don't have an option (yei! and I have to use an outdated version!!).
My suggestion is to create a virtual table:
From:
SELECT * FROM table
To:
CREATE VIEW v_table AS
SELECT ROW_NUMBER() OVER (ORDER BY table_key) AS row,* FROM table
Then just query:
SELECT * FROM v_table WHERE row BETWEEN 10 AND 20
If fields are added, or removed, "row" is updated automatically.
The main problem with this option is that ORDER BY is fixed. So if you want a different order, you would have to create another view.
UPDATE
There is another problem with this approach: if you try to filter your data, it won't work as expected. For example, if you do:
SELECT * FROM v_table WHERE field = 'test' AND row BETWEEN 10 AND 20
WHERE becomes limited to those data which are in the rows between 10 and 20 (instead of searching the whole dataset and limiting the output).
In SQL there's no LIMIT keyword exists. If you only need a limited number of rows you should use a TOP keyword which is similar to a LIMIT.
Must try. In below query, you can see group by, order by, Skip rows, and limit rows.
select emp_no , sum(salary_amount) from emp_salary
Group by emp_no
ORDER BY emp_no
OFFSET 5 ROWS -- Skip first 5
FETCH NEXT 10 ROWS ONLY; -- limit to retrieve next 10 row after skiping rows
Easy way
MYSQL:
SELECT 'filds' FROM 'table' WHERE 'where' LIMIT 'offset','per_page'
MSSQL:
SELECT 'filds' FROM 'table' WHERE 'where' ORDER BY 'any' OFFSET 'offset'
ROWS FETCH NEXT 'per_page' ROWS ONLY
ORDER BY is mandatory
This is a multi step approach that will work in SQL2000.
-- Create a temp table to hold the data
CREATE TABLE #foo(rowID int identity(1, 1), myOtherColumns)
INSERT INTO #foo (myColumns) SELECT myData order By MyCriteria
Select * FROM #foo where rowID > 10
SELECT
*
FROM
(
SELECT
top 20 -- ($a) number of records to show
*
FROM
(
SELECT
top 29 -- ($b) last record position
*
FROM
table -- replace this for table name (i.e. "Customer")
ORDER BY
2 ASC
) AS tbl1
ORDER BY
2 DESC
) AS tbl2
ORDER BY
2 ASC;
-- Examples:
-- Show 5 records from position 5:
-- $a = 5;
-- $b = (5 + 5) - 1
-- $b = 9;
-- Show 10 records from position 4:
-- $a = 10;
-- $b = (10 + 4) - 1
-- $b = 13;
-- To calculate $b:
-- $b = ($a + position) - 1
-- For the present exercise we need to:
-- Show 20 records from position 10:
-- $a = 20;
-- $b = (20 + 10) - 1
-- $b = 29;
If your ID is unique identifier type or your id in table is not sorted you must do like this below.
select * from
(select ROW_NUMBER() OVER (ORDER BY (select 0)) AS RowNumber,* from table1) a
where a.RowNumber between 2 and 5
The code will be
select * from limit 2,5
better use this in MSSQLExpress 2017.
SELECT * FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) as [Count], * FROM table1
) as a
WHERE [Count] BETWEEN 10 and 20;
--Giving a Column [Count] and assigning every row a unique counting without ordering something then re select again where you can provide your limits.. :)
One of the possible way to get result as below , hope this will help.
declare #start int
declare #end int
SET #start = '5000'; -- 0 , 5000 ,
SET #end = '10000'; -- 5001, 10001
SELECT * FROM (
SELECT TABLE_NAME,TABLE_TYPE, ROW_NUMBER() OVER (ORDER BY TABLE_NAME) as row FROM information_schema.tables
) a WHERE a.row > #start and a.row <= #end
If i remember correctly (it's been a while since i dabbed with SQL Server) you may be able to use something like this: (2005 and up)
SELECT
*
,ROW_NUMBER() OVER(ORDER BY SomeFields) AS [RowNum]
FROM SomeTable
WHERE RowNum BETWEEN 10 AND 20

What is the error in my query?

in below query it returns 12 record while query in from clause (as t) returns 18 record, can anyone help what is the issue in this query?
SELECT count(abc.id) as total_this_month,t.*
FROM email_details abc
JOIN
(SELECT count(email_details.id) as total_emails,MAX(`email_details`.email_date) as email_date1, `email_details`.* FROM (`cld_users` join email_details on email_details.fk_user_id = cld_users.id) GROUP BY `email_details`.`email_title` ORDER BY `email_details`.`email_date` DESC) as t
ON abc.email_title = t.email_title
where (MONTH(abc.email_date)=MONTH(NOW()) AND YEAR(abc.email_date)=YEAR(NOW()))
group by t.email_title
ORDER BY t.`email_date` DESC
In your query, you specify
where (MONTH(abc.email_date)=MONTH(NOW()) AND YEAR(abc.email_date)=YEAR(NOW()))
But in the subquery (the one returning 18 results), you have 6 emails with a month that is not december 2014. There's no way that those emails can be returned by a query that explicitly excludes them.
You want those emails as well so you get 18 results ? Remove the WHERE clause excluding them:
SELECT Count(abc.id) AS total_this_month,
t.*
FROM email_details abc
JOIN (SELECT Count(email_details.id) AS total_emails,
Max(`email_details`.email_date) AS email_date1,
`email_details`.*
FROM (`cld_users`
JOIN email_details
ON email_details.fk_user_id = cld_users.id)
GROUP BY `email_details`.`email_title`
ORDER BY `email_details`.`email_date` DESC) AS t
ON abc.email_title = t.email_title
GROUP BY t.email_title
ORDER BY t.`email_date` DESC
Starting from there, if you want to count the emails from the current month, simply replace:
SELECT Count(abc.id) AS total_this_month,
with
SELECT SUM(CASE WHEN MONTH(abc.email_date)=MONTH(NOW()) AND YEAR(abc.email_date)=YEAR(NOW()) THEN 1 ELSE 0 END) AS total_this_month,

How to perform multiple table operations in mysql?

I just want to perform multiple table operations in single query. The query is:
select name,sno , id as ids ,(select sum(amount) from client_credits
where user_id = ids) As total from clients where sno = '4' and total > '0'
This query is not working when I am trying use ** total > 0 **. Is there any other possibility ways? Please help me.
total is an alias. Aliases are not resolved when the WHERE clause is reached.
Try: where sno = 4 having total > 0
Alternatively, and more efficiently:
SELECT `c`.`name`, `c`.`sno`, `c`.`id`, SUM(`ccr`.`amount`) AS `total`
FROM `clients` AS `c`
JOIN `client_credits` AS `ccr` ON `c`.`id`=`ccr`.`user_id`
WHERE `c`.`sno` = 4
GROUP BY `c`.`id`
Notice how the total > 0 part is gone? That's because if there are no rows to join, then nothing will be joined and the rows are removed from the result ;)

finding the maximum value of a field of a MySQL query result

I have this Query :
select
id_re_usr,
year(time) as AYear,
DAYOFYEAR(time) as ADay,
DATE_FORMAT(time, "%m-%d-%y") as date,
count(*) as TotalPerDay
from numrequest
where id_re_usr = "u1"
group by id_re_usr, AYear, ADay
order by AYear, ADay
it outputs something like
date TotalPerDay
------------------------
01-01-87 1
01-09-12 5
02-09-12 17
03-09-12 1
how can I find the maximum TotalPerDay without changing the current output by using php or changing the query.
I tried to do this and it works
$max=0;
while($row=mysql_fetch_array($results)){
if($max<$row['TotalPerDay']){ $max= $row['TotalPerDay'];}
}
but isn't there a direct way to do it?
if modifying the query the output should be
date TotalPerDay max
----------------------------------------
01-01-87 1 17
01-09-12 5 17
02-09-12 17 17
03-09-12 1 17
Join it to a second query of just the max count.. The inner-most queries on a per day basis (for the given user) a set of rows on count grouped per day. From that, the next outer does a select MAX() from that set to find and get only one record representing the highest day count... Since it will always return a single row, and joined to the original numRequest table it will be a Cartesian, but no problem since its only one record and you want that value on every returned row anyhow.
select
id_re_usr,
year(time) as AYear,
DAYOFYEAR(time) as ADay,
DATE_FORMAT(time, "%m-%d-%y") as date,
count(*) as TotalPerDay,
HighestCount.Max1 as HighestOneDayCount
from
numrequest,
( select max( CountsByDate.DayCount ) Max1
from ( select count(*) as DayCount
from numrequests nr
where nr.id_re_usr = "u1"
group by date( nr.time )) CountsByDate
) HighestCount
where
id_re_usr = "u1"
group by
id_re_usr,
AYear,
ADay
order by
AYear,
ADay

Categories