select increment counter reset by user in mysql - mysql

I read about create variable for increment in select in this post select increment counter in mysql
I need some addition to this query.. I need to reset the increment based on user_id.
Sample data :
id user_id name
1 1 A
2 2 B
3 3 C
4 1 D
5 2 E
6 2 F
7 1 G
8 3 H
Expected result:
id user_id name increment
1 1 A 1
4 1 D 2
7 1 G 3
2 2 B 1
5 2 E 2
6 2 F 3
3 3 C 1
8 3 H 2
It's not stop only until 3 increments, if I have more row with user_id, it will continue the increment.
How do I make query so the output look like that? Thanks!

Try this:
SELECT A.*, CASE WHEN id=user_id THEN 1
WHEN id>user_id THEN 2
ELSE 0 END increment
FROM yourTable A
ORDER BY A.user_id;
See it run on SQL Fiddle.

You do not need a variable to do that. simple COUNT(), and GROUP BY would do the trick.
SELECT user_id, name, COUNT(user_id) AS increment FROM your_table GROUP BY user_id;
But this will return a single value for one user.
This will pass all count.
SELECT user_id, name, (SELECT COUNT(t2.user_id) FROM your_table t2 WHERE t2.user_id=t1.user_id) AS increment FROM your_table t1;
I'm not a expert at larevel. This is a simple PHP code.
<?php
$db = new mysqli("localhost","root","","test");
$sql = $db->query("SELECT * FROM your_table ORDER BY user_id");
$name_array = array();
$array_counts = array();
?>
<table>
<tr>
<th>id</th>
<th>user id</th>
<th>name</th>
<th>increment</th>
</tr>
<?php
while ($row = $sql->fetch_assoc()){
if (in_array($row['user_id'],$name_array)){
$array_counts[$row['user_id']][0] = $array_counts[$row['user_id']][0]+1;
} else {
$array_counts[$row['user_id']][0] = 1;
}
array_push($name_array,$row['user_id']);
?>
<tr>
<td><?php echo $row['id']; ?></td>
<td><?php echo $row['user_id']; ?></td>
<td><?php echo $row['name']; ?></td>
<td><?php echo $array_counts[$row['user_id']][0]; ?></td>
</tr>
<?php
}
?>
</table>

I was looking for something similar and I may have worked it out (maybe it wasn't exactly what you were looking for) :
SET #increment := 0;
SET #user_id_mem := 0;
SELECT
#increment := CASE WHEN tbl.user_id = #user_id_mem THEN (#increment+1) ELSE 1 END as increment,
tbl.id,
#user_id_mem := tbl.user_id,
tbl.name
FROM YOURTABLE tbl
ORDER BY user_id;

Related

NHL standings in SQL

I have an SQL query that produces team standings based off the old NHL format. The first section of the code gets the top 3 teams in each division, and the 2nd bit gets the rest and sorts them by points/differential.
This can be seen here: http://rgmgstandings.tk
Here is my SQL query:
("(SELECT *, 1 as `SortKey` from `standings_east`
WHERE pts = (select max(pts)
from standings_east as t
where t.`div` = standings_east.`div`))
UNION ALL
(select *, 2 as SortKey from `standings_east`
where team not in
(select team from standings_east
where pts = (select max(pts)
from standings_east as t
where t.`div` = standings_east.`div`)))
order by SortKey, pts desc, diff desc")
If you visit my website, and look at the standings for the Western Conference (blue banner), you will notice 3 teams in 'CEN' that have the same amount of points (Chicago, Winnipeg, Columbus)
I want the query to select only ONE team from that division based on whoever has the most 'Wins/W'.
The correct standings should be:
Edmonton (NW) 80
Anaheim (PAC) 74
Columbus (CEN) 71
Dallas (PAC) 73
Chicago (CEN) 71
Winnipeg (CEN) 71
How can I accomplish this?
Query
select team,`div`,pts,1 as sortOrder
from
( -- note use parentheses to avoid mysql error 1221
(select team,`div`,pts,#cen:=team from `standings_west` where `div`='CEN' order by pts desc limit 1)
union all
(select team,`div`,pts,#pac:=team from `standings_west` where `div`='PAC' order by pts desc limit 1)
union all
(select team,`div`,pts,#nw:=team from `standings_west` where `div`='NW' order by pts desc limit 1)
) xDerived1
cross join (select #cen='',#pac='',#nw='') params
union
select team,`div`,pts,sortOrder
from
( select team,`div`,pts,2 as sortOrder
from `standings_west`
where team!=#cen and team!=#pac and team!=#nw
order by pts desc
limit 3
) xDerived2
order by sortOrder,pts desc;
Results
+----------+-----+-----+-----------+
| team | div | pts | sortOrder |
+----------+-----+-----+-----------+
| EDMONTON | NW | 80 | 1 |
| ANAHEIM | PAC | 74 | 1 |
| WINNIPEG | CEN | 71 | 1 |
| DALLAS | PAC | 73 | 2 |
| CHICAGO | CEN | 71 | 2 |
| COLUMBUS | CEN | 71 | 2 |
+----------+-----+-----+-----------+
Stored Proc
The following depicts a stored proc just to show it in case you are having problems and need it.
drop procedure if exists xdoit;
delimiter $$
create procedure xdoit()
begin
select team,`div`,pts,1 as sortOrder
from
( -- note use parentheses to avoid mysql error 1221
(select team,`div`,pts,#cen:=team from `standings_west` where `div`='CEN' order by pts desc limit 1)
union all
(select team,`div`,pts,#pac:=team from `standings_west` where `div`='PAC' order by pts desc limit 1)
union all
(select team,`div`,pts,#nw:=team from `standings_west` where `div`='NW' order by pts desc limit 1)
) xDerived1
cross join (select #cen='',#pac='',#nw='') params
union
select team,`div`,pts,sortOrder
from
( select team,`div`,pts,2 as sortOrder
from `standings_west`
where team!=#cen and team!=#pac and team!=#nw
order by pts desc
limit 3
) xDerived2
order by sortOrder,pts desc;
end$$
delimiter ;
call stored proc
call xdoit();
A few comments here.
First, your sqlfiddle had data from the west, but a query from the east. Based on table names, I suggest you have all your data in one table not two and have a column for east or west.
The query uses a cross join to merely establish variables for grabbing the division leaders so those division leaders are excluded for the sortOrder=2 teams.
Tweak as necessary for tie-breaks (ie: the teams with 71 points) regarding your implemention of DIFF in comments to #Clockwork
Ask if you have any questions.
The following is the multi_query php solution I came up with for you based on your posting of a comment in that chat room.
The only solution I could come up with was the following based on clearly the results were coming back in two result sets. Thus the while loop that is driven by next_result(). The first result set has the top 3 rows, the 2nd result set has the twelve rows that follow. That is just the way PHP seems to see it.
Also note that in the PHP part, since I seemed to be dealing with a multi_query, I took advantage of that and passed the mysql parameters in versus doing a cross join to pick them up.
PHP
<!DOCTYPE html>
<html lang="en">
<head>
<title>RGMG: Standings</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</head>
<body>
<?php
//mysqli_report(MYSQLI_REPORT_ALL);
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
error_reporting(E_ALL); // report all PHP errors
ini_set("display_errors", 1);
try {
$mysqli= new mysqli('localhost', 'dbUser', 'thePassword', 'theDbName');
echo "<table><div><br><br>"; // note you had this line a little bit wrong
// notice below the concat of the $sql and the multi_query()
$sql = "set #cen:='',#pac:='',#nw:=''; ";
$sql .= "select *
from
( select team,`div`,gp,win,lose,otl,goalsF,goalsA,diff,gpg,gaa,pts,1 as sortOrder
from
( -- note use parentheses to avoid mysql error 1221
(select team,`div`,gp,win,lose,otl,goalsF,goalsA,diff,gpg,gaa,pts,#cen:=team from `standings_west` where `div`='CEN' order by pts desc, win desc, diff desc limit 1)
union all
(select team,`div`,gp,win,lose,otl,goalsF,goalsA,diff,gpg,gaa,pts,#pac:=team from `standings_west` where `div`='PAC' order by pts desc, win desc, diff desc limit 1)
union all
(select team,`div`,gp,win,lose,otl,goalsF,goalsA,diff,gpg,gaa,pts,#nw:=team from `standings_west` where `div`='NW' order by pts desc, win desc, diff desc limit 1)
) xDerived1
union all
select team,`div`,gp,win,lose,otl,goalsF,goalsA,diff,gpg,gaa,pts,sortOrder
from
( select team,`div`,gp,win,lose,otl,goalsF,goalsA,diff,gpg,gaa,pts,2 as sortOrder
from `standings_west`
where team!=#cen and team!=#pac and team!=#nw
order by pts desc
) xDerived2
) xDerived3
order by sortOrder,pts desc";
echo "<div class='container'>";
echo "<img src='http://i.imgur.com/sjDHhIV.png' width='100%' alt='West'>";
echo "<table class='table table-condensed'>
<tr class='top'>
<th class='rank'></th>
<th class='team'>TEAM</th>
<th>DIV</th>
<th>GP</th>
<th>W</th>
<th>L</th>
<th class='otl'>OTL</th>
<th class='pts'>PTS</th>
<th>GF</th>
<th>GA</th>
<th>DIFF</th>
<th>GPG</th>
<th>GAA</th>
";
$counter=1;
$mysqli->multi_query($sql);
while(true) {
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_assoc()) {
$gpg = ($row['goalsF']);
$gaa = ($row['goalsA']);
if ($row['gp'] != 0 ){
$gpg = ($row['goalsF'] / $row['gp']);
$gaa = ($row['goalsA'] / $row['gp']);
}
else {
$row['gp'] = "";
}
echo "<tr>
<td class='rank'>" . "$counter" . "</td>
<td class='team'>" . $row['team'] . "</td>
<td>" . $row['div'] . "</td>
<td>" . $row['gp'] . "</td>
<td>" . $row['win'] . "</td>
<td>" . $row['lose'] . "</td>
<td class='otl'>" . $row['otl'] . "</td>
<td class='pts'>" . $row['pts'] . "</td>
<td>" . $row['goalsF'] . "</td>
<td>" . $row['goalsA'] . "</td>
<td>" . $row['diff'] . "</td>
<td>" . round($gpg, 2) . "</td>
<td>" . round($gaa, 2) . "</td>";
$counter++;
}
$result->free();
}
if ($mysqli->more_results()) {
$mysqli->next_result();
}
else {
break;
}
}
echo "</table></div>";
$mysqli->close();
} catch (mysqli_sql_exception $e) {
throw $e;
}
?>
</body>
</html>
First i love NHL and from your query we can say the table you are showing us is standings_east,so let's try this:
select team,DIV,GP,W,L,OTL,PTS,GF,GA,DIFF,GPG,GAA,1 as sort_key
from standings_east t
where exists
(select 1
from
(select DIV,max(PTS) as PTS,max(W) as W from standings_east
group by DIV) a
where t.DIV=a.DIV and t.PTS=a.PTS and t.W=a.W
)
UNION ALL
select team,DIV,GP,W,L,OTL,PTS,GF,GA,DIFF,GPG,GAA,2 as sort_key
from standings_east t
where not exists
(select 1
from
(select DIV,max(PTS) as PTS,max(W) as W from standings_east
group by DIV) a
where t.DIV=a.DIV and t.PTS=a.PTS and t.W=a.W
)
order by sort_key,PTS DESC
i think there is some better way but this is the one like yours the most and the easiest to understand just add a group by on your code and Merry Christmas

Select Count and Then Order By

I am having some problems trying to find the members with the most referrals.. I have been looking up stuff and trying stuff for more than 3 hours so this is my last resort. My goal is to list the members username and the amount of referrals they have..
So each members referral is marked by their id..
so in the example test2 is orig's ref. So each persons ref is marked by their id.
id | username | ref
1 | orig |0 (for none)
2 | test2 |1 (orig id)
3 | another |1 (orig id)
and the goal is to echo this out. If it is even possible.
UserName | Refs
test 1
test2 0
my attempt. It gives me the amount but it does not order them and echoes to many.
$result = mysql_query("SELECT * FROM members");
echo '<table class="table table-bordered"><tr><th>Credits</th><th>Username</th></tr>';
while($row = mysql_fetch_array($result))
{
$contest_id = $row['id'];
$result1 = mysql_query("SELECT COUNT(*) FROM members WHERE ref=".$row['id']."");
while($row1=mysql_fetch_array($result1))
{
$result_c = mysql_query("SELECT * FROM members ORDER BY ".$row1['COUNT(*)']."+0 DESC Limit 10");
while($row_c = mysql_fetch_array($result_c))
{
$top_id = $row_c['id'];
$find_c = mysql_query("select count(*) from members where user_id='$top_id'");
$found_c = mysql_result($find_c,0);
echo '<tr><td>';
echo $found_c;
echo '</td>';
echo '<td>';
echo $row_c['username'];
echo '</td>';
echo '</tr>';
}}}
echo '</table>';
If I understood your table lay-out correctly, this should do the trick.
SELECT t1.username, t2.numref
FROM members t1
LEFT JOIN (SELECT ref, COUNT(ref) as numref
FROM members
GROUP BY ref) t2
ON t2.ref = t1.id
ORDER BY numref DESC
It should provide a NULL value in the numref column for the users that haven't made any referrals.
For reference, I added a SQL-Fiddle!

mysql count distinct positive values but count all -1 values in table and give total?

i have a table called ptb_profile_views that looks like this:
id | profile_id | viewed_profile_id
1 2 6
2 2 6
3 3 6
4 -1 6
5 -1 6
i have been trying to count the positive values in 'profile_id' only once as distinct values and count -1 values as many times as they appear with the following query:
function check_profile_views3() {
global $connection;
global $_SESSION;
$query = "
SELECT id,profile_id,viewed_profile_id COUNT
FROM ptb_profile_views
WHERE profile_id > 0
GROUP BY profile_id
UNION
/*shows all -1 profile id's*/
SELECT id,profile_id,viewed_profile_id
FROM ptb_profile_views
WHERE profile_id <= 0";
$check_profile_views_set3 = mysql_query($query, $connection);
confirm_query($check_profile_views_set3);
return $check_profile_views_set3;
}
so the end result is
2, 3, -1, -1
but instead of echoing out the actual values them selves i want the query to do a count of the values.
so...
2, 3, -1, -1 = a total of 4
i am also trying to call the query like so which i don't know if will work:
$check_profile_views_set3 = check_profile_views3();
while ($views3 = mysql_fetch_array($check_profile_views_set3)) {
echo "".$views3['profile_id'].""; ?>
can someone please show me how i can do this? thanks
SELECT a + b AS TotalCount
FROM
(
SELECT COUNT(DISTINCT profile_ID) a
FROM ptb_profile_views
WHERE profile_ID > 0
) x,
(
SELECT COUNT(profile_ID) b
FROM ptb_profile_views
WHERE profile_ID < 0
) y
SQLFiddle Demo

Select rows from a table where all values of an array exist

I have this query that retreives a list of id's + NAME:
$sql = "SELECT id FROM #__table1 ";
$sql .= " WHERE (";
foreach($explode_tags as $k=>$explode_tag) {
$sql .= "name = ".$db->Quote(trim($explode_tag));
if(($k+1) != count($explode_tags))
$sql .= " OR ";
}
$sql .= ")";
$db->setQuery($sql);
$results = $db->loadResultArray();
The result is an array like this:
keywordID | NAME
1 cat
2 dog
3 horse
Now I have this table2:
id | ItemID | keywordID
1 4 1
2 4 2
3 4 3
4 6 1
5 6 2
6 7 1
I want to find from table2 all ItemID's that have all keywordID's found in table1.
In the example above I want to return only itemID 4 that has all keywords (all 3 of them).
I am running this query but I am not getting results:
...
$query .= " AND i.id IN (SELECT itemID FROM #__table2 WHERE (";
foreach($results as $k=>$result) {
$query .= "keywordID = ".(int)$result;
if(($k+1) != count($results))
$query .= " AND ";
}
$query .= "))";
UPDATE
Sorry, I miss read your question. I've done simple test using this data:
id itemId keywordId
1 4 1
5 4 2
6 4 3
7 5 2
8 5 3
9 6 1
10 6 2
11 6 3
12 7 3
13 9 3
14 9 2
15 9 1
and using this query:
SELECT itemId, GROUP_CONCAT( keywordId ORDER BY keywordId ) AS crpcnct, COUNT( itemId )
FROM `temporary_table_123`
GROUP BY 1
HAVING crpcnct = '1,2,3'
I can get the value that you wanted:
itemId crpcnct count(itemId)
4 1,2,3 3
6 1,2,3 3
9 1,2,3 3
To achieve this, all you have to do is build the keywordID you want to use:
$keywordIds[] = $results['keywordId'];
and then sort accending
sort($keywordIds);
the last step is, supply this array into query:
SELECT itemId, GROUP_CONCAT( keywordId ORDER BY keywordId ) AS crpcnct, COUNT( itemId )
FROM `temporary_table_123`
GROUP BY 1
HAVING crpcnct = '" . implode(",", $keywordIds) . "'
There you have it.
SELECT ItemID FROM table2 WHERE keywordID IN (SELECT keywordID FROM table1)
This might work. I'll have to create local copies of your tables to see for sure, though.
$array_names = array();
foreach($explode_tags as $k=>$explode_tag){
$array_names[] = 'name = ' . $db->Quote(trim($explode_tag));
}
$sql = "SELECT ItemID FROM table_2 WHERE keywordID IN (SELECT keywordID FROM table_1 WHERE " . implode(' OR ', $array_names) .")";
$db->setQuery($sql);
$results = $db->loadResultArray();

Does MySQL table row contain two values

I have a table with two columns:
ID1 | ID2
---------
1 | A
3 | V
1 | C
4 | B
5 | Q
1 | S
And I want to be able to find out if any row has, say ID1 = 5 and ID2 = Q , and return a true / false value.
Yes, Of course
SELECT * FROM table where ID1='5' and ID2='Q'
PHP (I am just guessing this backend)
$query = "SELECT * FROM table where ID1='5' and ID2='Q'";
$result = mysql_query($query);
if(mysql_num_rows($result)) { return true; }
else { return false; }
1 means TRUE for mysql
SELECT 1
FROM your_table
WHERE ID1 = 5 AND ID2 = 'Q'
for example this?
SELECT 1
FROM TABLE
WHERE ID1 = 5 AND ID2 = 'Q'
Efficient query for your purpose (faster than other examples):
SELECT 1 FROM table where ID1='5' and ID2='Q' LIMIT 1
PHP sample:
<?php
$query = "SELECT 1 FROM table where ID1='5' and ID2='Q' LIMIT 1";
echo bool(mysql_num_row(mysql_query($query)));
?>