Mysql make count value increment with 1 - mysql

I want to add multiple counter in other column.
I have a two row in mysql database and i have multiple id in second column so i want to add counter like 1,2,3... in other column.
my screenshort are given below :
In image are 1889 are twice and i want these two means all duplicate value make increment with 1.
expected output :
1889 dell1
1889 dell2
1890 dell0
1891 dell0
Above 1889 are twice so output is 1889 dell1 ,1889 dell2.
1890 and 191 is single so output is 0 behind dell.
so i want increment with 1 behind dell.
if anyone know mysql query so please inform me.

The question that you are mentioning it here is an example of rank by partition. Oracle has in-built functions to obtain such output, but MySQL doesn't have something like that.
select result.YEAR, CONCAT(result.NAME,'',result.rank) from (
SELECT name,
year,
IF(year=#last,#curRank:=#curRank+1,#curRank:=0) AS rank,
#_sequence:=#_sequence+1,
#last:=year
FROM COMPUTER , (SELECT #curRank := 1, #_sequence:=1, #last:=0) r
ORDER BY year asc) as result;
You can refer the fiddle here
I have taken reference from this another answer here.

Related

MySQL virtually calculated column for ranking

I have a table that saves user scores in games, structured like this:
user_id (int)
game_id (int)
score (int)
I want to add another column to this table which will be a virtual column that holds the ranking of user for a game (like a table).
For example
user_id game_id score rank (virtual)
1 1 50 1
2 1 48 2
3 1 40 3
2 2 80 1
1 2 50 2
3 2 32 3
As you can see, the rank column is virtually calculated by the points in each game.
Is it even possible? And if so, what should I write in the virtuality expression field?
This doesn't account for ties, but may get you started...
SELECT x.*
, CASE WHEN #prev = game_id THEN #i:=#i+1 ELSE #i:=1 END rank
, #prev := game_id
FROM my_table
, (SELECT #prev:=null,#i:=0) vars
ORDER
BY gamed_id, score DESC;
No, it is not possible to use a generated column for calculating rank. As MySQL documentation on generated columns says:
Subqueries, parameters, variables, stored functions, and user-defined functions are not permitted.
To calculate the rank, you would have to determine the position of the record using a certain ordering within the entire table. This would require an expression that can check other records. There are no such functions within MySQL and subqueries are not allowed.
The only way to make this work is via a view, where you are allowed to use variables and subqueries to calculate the ranking.
Note, that this may change with MySQL v8.0 because it has rank() and dense_rank() functions. You have to experiment whether these functions are allowed in generated columns (I'm not sure if they are deterministic).

Iterate through a column and summarize findings

I have a table (t1) in mySQL that generates the following table:
type time full
0 11 yes
1 22 yes
0 11 no
3 13 no
I would like to create a second table (t2) from this that will summarize the information found in t1 like the following:
type time num_full total
0 11 1 2
1 22 1 1
3 13 0 1
I want to be able to iterate through the type column in order to be able to start this summary, something like a for-loop. The types can be up to a value of n, so I would rather not write n+1 WHERE statements, then have to update the code every time more types are added.
Notice how t2 skipped the type of value 2? This has also been escaping me when I try looping. I only want the the types found to have rows created in t2.
While a direct answer would be nice, it would be much more helpful to be pointed to some sources where I could figure this out, or both.
This may do what you want
create table t2 if not exists select type, time, sum(full) num_full, count(*) count
from t1
group by type,time
order by type,time;
depending on how you want to aggregate the time column.
This is a starting point for reference on the group by functions : https://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html
here for create syntax
https://dev.mysql.com/doc/refman/5.6/en/create-table.html

MySQL Sum and Case Query

I create a ReportViewer with VB.NET connecting to a MySQL database. The data appears like below.
IdProduct Quantity TotalPrice OrderDate
0001 1 10 29/09/2014
0002 2 40 29/09/2014
0001 4 40 29/09/2014
0001 2 20 29/09/2014
0001 2 20 29/09/2014
Based on the records above, I'd like the result to appear like below
0001 0002
9 2
90 40
What is Query Sum Case the best use here? Thanks in advance.
NOTE: It's not possible for a query to "dynamically" alter the number or datatype of the columns returned, those must be specified at the time the SQL text is parsed.
To return the specified resultset with a query, you could do something like this:
SELECT SUM(IF(t.IdProduct='0001',t.Quantity,NULL)) AS `0001`
, SUM(IF(t.IdProduct='0002',t.Quantity,NULL)) AS `0002`
FROM mytable t
UNION ALL
SELECT SUM(IF(t.IdProduct='0001',t.TotalPrice,NULL)) AS `0001`
, SUM(IF(t.IdProduct='0002',t.TotalPrice,NULL)) AS `0002`
FROM mytable t
Note that the datatypes returned by the two queries will need to be compatible. This won't be a problem if Quantity and TotalPrice are both defined as integer.
Also, there's no specific guarantee that the "Quantity" row will be before the "TotalPrice" row; we observe that behavior, and it's unlikely that it will ever be different. But, to have a guarantee, we'd need an ORDER BY clause. So, including an additional discriminator column (a literal in the SELECT list of each query), that would give us something we could ORDER BY.
Note that it's not possible to have this single query dynamically create another column for IdProduct '0003'. We'd need to add that to the SELECT list of each query.
We could do this in two steps, using a query to get the list of distinct IdProduct, and then use that to dynamically create the query we need.
BUT... with all that said... we don't want to do that.
The normative pattern would be to return Quantity and TotalPrice as two separate columns, along with the IdProduct as another column. For example, the result returned by this statement:
SELECT t.IdProduct
, SUM(t.Quantity) AS `Quantity`
, SUM(t.TotalPrice) AS `TotalPrice`
FROM mytable t
GROUP BY t.IdProduct
And then the client application would be responsible for transforming that resultset into the desired display representation.
We don't want to push that job (of transforming the result into a display representation) into the SQL.
select idproduct, sum(quantity), sum(totalprice)
from your_table
group by idproduct

Mysql grouped ranking

Related to this question.
Actually lest say we want to solve the grouped ranking problem in mysql. We have a table that each row represents an entity, that belongs to a group. We want to assign a rank for each entity based on an attribute separate for each group. Later we could do various manipulations with the rank, like asking for the first 10 entities of each group that satisfy another condition as well, etc.
For example, the entity could be programmers that belong to different "groups" according to their favorite programming language. Then each programmer has a reputation (let's say in forum). We want to add an extra field that would be the programmer's rank based on descending reputation. We want to do this independently for each group.
gid | repu | name |
1 1 john
1 3 anna
2 2 scot
2 1 leni
to become
gid | repu | name | rank
1 3 anna 1
1 1 john 2
2 2 scot 1
2 1 leni 2
Now let's also demand that we do not want to use session variables based solutions. Yes they work pretty well but they clearly violate the mysql demand for not to read and write a session variable on the same statement. (See here)
Now a proposed solution in this post says
-- SOL #1 (SELF-JOIN)
SELECT a.*, count(*) as row_number FROM test a
JOIN test b ON a.gid = b.gid AND a.repu <= b.repu
GROUP BY a.gid, a.repu
Which pretty much does the thing. Some questions I have are, is this legit SQL or does it violate any standard or mysql quirk? Is is guaranteed that it will work on mysql ?
Also another solution that I read here is, which is more of a black magic for me but seems more elegant
-- SOL #2 (SUBQUERY)
SELECT t.* ,
( SELECT COUNT(*) + 1
FROM test
WHERE repu > t.repu AND gid = t.gid
) AS rank
FROM test AS t
ORDER BY gid ASC, rank ASC
This uses a sub query that references an outer table, and does the trick also. Could anybody explain how this one works ?
Also, the same questions here as for solution #1.
Plus any comments on evaluating the performance/compatibility of two proposed solutions.
EDIT: Aditional methods, for the reference
From this post one variation of the session variable method. WARNING: This is that I want to avoid. Notice that in a single statement that #rand and #partition session variables are read (in the case after WHEN and THEN) and written (in the CASE after THEN AND ELSE and also in the next subquery that initializes the variables).
-- SOL #3 (SESSION VARIABLES / ANTIPATTERN)
SELECT t.*, ( CASE gid
WHEN #partition THEN #rank := #rank + 1
ELSE #rank := 1 AND #partition := gid ) AS rank
FROM test t,
(SELECT #rank := 0, #partition := '') tmp
ORDER BY gid ASC, repu DESC
Also here is the set based solution, rather complicated, posted by a fellow bellow.
-- SOL #4 (SET BASED)
SELECT x.*, FIND_IN_SET(CONCAT(x.gid,':',x.repu), y.c) rank
FROM test x
JOIN (
SELECT GROUP_CONCAT(DISTINCT CONCAT(gid,':',repu) ORDER BY gid, repu DESC) c
FROM test GROUP BY gid
) y ON FIND_IN_SET(CONCAT(x.gid,':',x.repu), y.c)
JOIN is legit MYSQL syntax. If it wasn't working, doubt anyone would mark it as the answer.
In terms of subquery, it will be less faster than the first solution. Looking at EXPLAIN PLAN would be a great idea to understand the execution of these queries.
There's another way to achieve the same:-
-- SOL #3: Answer with 30 votes in this post:
ROW_NUMBER() in MySQL

Complex MySQL COUNT query

Evening folks,
I have a complex MySQL COUNT query I am trying to perform and am looking for the best way to do it.
In our system, we have References. Each Reference can have many (or no) Income Sources, each of which can be validated or not (status). We have a Reference table and an Income table - each row in the Income table points back to Reference with reference_id
On our 'Awaiting' page (the screen that shows each Income that is yet to be validated), we show it grouped by Reference. So you may, for example, see Mr John Smith has 3 Income Sources.
We want it to show something like "2 of 3 Validated" beside each row
My problem is writing the query that figures this out!
What I have been trying to do is this, using a combination of PHP and MySQL to bridge the gap where SQL (or my knowledge) falls short:
First, select a COUNT of the number of incomes associated with each reference:
SELECT `reference_id`, COUNT(status) AS status_count
FROM (`income`)
WHERE `income`.`status` = 0
GROUP BY `reference_id`
Next, having used PHP to generate a WHERE IN clause, proceed to COUNT the number of confirmed references from these:
SELECT `reference_id`, COUNT(status) AS status_count
FROM (`income`)
WHERE `reference_id` IN ('8469', '78969', '126613', ..... etc
AND status = 1
GROUP BY `reference_id`
However this doesn't work. It returns 0 rows.
Any way to achieve what I'm after?
Thanks!
In MySQL, you can SUM() on a boolean expression to get a count of the rows where that expression is true. You can do this because MySQL treats true as the integer 1 and false as the integer 0.
SELECT `reference_id`,
SUM(`status` = 1) AS `validated_count`,
COUNT(*) AS `total_count`
FROM `income`
GROUP BY `reference_id`