I'm trying to count a certain field and how much it occurs based on a date. For example, I have a reputation field that I need counted, so if there is 5 reputation points that were individually submitted on 12/14/2014, how would I get the total amount and not just 5 rows?
This is an example of what I am trying to do (if it helps explain it better)
'ID' => 1,
'rep' => 'SK01',
'25/11/14' => '5',
'26/11/14' => '23',
'27/11/14' => '3',
'28/11/14' => '87',
'29/11/14' => '4',
'01/12/14' => '45',
'02/12/14' => '145',
On today [ 2014-12-08 09:53:27 ] there were 1 for AH05 (I'm just getting a repeat of that however many times it is in table) Here is the SQL also if that helps
SELECT *, COUNT(*) as TotalValueCount, DATE(date_created) AS thedate
FROM wp_rg_lead INNER JOIN wp_rg_lead_detail ON wp_rg_lead.id = wp_rg_lead_detail.lead_id
WHERE wp_rg_lead.form_id = '47' AND date_created BETWEEN DATE_SUB(NOW(), INTERVAL 7 DAY)
AND NOW() AND field_number = '18' GROUP BY value, date_created
You would do a group by query, but the results would be in rows, not columns:
select rep, date, count(*)
from table t
group by rep, date;
If, for some reason, you really have to have the values in columns, I would suggest doing it at the application layer. Otherwise, Google "MySQL dynamic pivot" to get ideas on what to do.
Related
I'm new in SQL and I need to group the results of a query by year.
In other words, I have this table structure:
id | title | date
My current query SELECT * FROM table
My current result:
array =>
0 =>
array =>
...
'date' => string '2018-03-09'
1 =>
array =>
...
'date' => string '2018-03-15'
2 =>
array =>
...
'date' => string '2017-03-15'
And I need something like that:
array =>
0 =>
array =>
...
'date' => string '2018-03-09'
array =>
...
'date' => string '2018-03-15'
1 =>
array =>
...
'date' => string '2017-03-15'
Thanks in advance for help :)
[EDIT]
I finally found a way to do what I wanted:
$result = $sql->query("SELECT * FROM abstract ORDER BY date DESC");
$array = [];
forEach($result as $res) {
$year = strtok($res['date'], '-');
if (!isset($array[$year]))
$array[$year][0] = $res;
else
array_push($array[$year], $res);
}
return $array;
If you want group data by year.
Select id,title,date,DATE_FORMAT(date, '%Y') YEAR_GRP from table group by YEAR_GRP
This is something you'll want to do in your query, as MySQL can do it much more efficiently, than PHP.
The way to do it is to add a GROUP BY clause to your query, which will batch rows in your resultset into a single row, based on a grouping value, which in your case will be YEAR(date), as you're looking to group items by the year component in each line's date.
Because you're still looking to have all the results returned, merely grouped by each distinct grouping value, you'll need to use an Aggregate Function to combine all the matching lines into an array of values. Luckily MySQL has a function called json_objectagg which does exactly what you need.
So you'll end up with a query that looks something like:
SELECT year(`date`) AS `year`, json_objectagg(id, `date`, title) AS `line`
FROM abstract
GROUP BY `year`
Instead of json_objectagg, alternatives are e.g. json_arrayagg
SELECT year(`date`) AS `year`, json_arrayagg(id, `date`, title) AS `line`
...or group_concat
SELECT year(`date`) AS `year`, group_concat(id, `date`, title) AS `line`
...depending on what kind of output you require.
I have two tables named "stats" and "users"
users table has all the typical user data like id,username,password,email(columns)
stats table has id,attack, defense,ostats,gold,food(columns)
I want to display data from these two tables side by side and have the data linked through their IDS
For example,
Rank user_uid ostats attack defense gold
1 Test 10 5 5 100
2 Test2 8 2 6 60
3 Test3 6 5 1 40
Username is from table "users" and the rest of them are from table "stats"
So first I want to know how to link and display the data from the same ID, like Username(user_id=1) and ostats,attack,defense,gold,food(id=1)
Then I want them in order by their "ostats" (I don't have a column named "rank" in any table yet, just don't know how to create the rank using overall stats)
You could do something like (untested)
SELECT u.username, s.overall, s.attack, s.defense, s.gold
FROM stats s JOIN users u on s.user_uid = u.id
ORDER BY s.overall;
Possible solution to ranking:
set #row_number=0;
SELECT (#row_number:=#row_number+1) as rank, u.username, s.overall, s.attack, s.defense, s.gold
FROM stats s JOIN users u on s.user_uid = u.id
ORDER BY s.overall;
Another, horrible looking attempt:
set #row_number = (select count(*) from users) + 1;
select (#row_number:=#row_number-1) as rank, u.username, s.overall from
stats s join users u on s.user_uid = u.id order by s.overall desc;
set #row_number = 0;
Here in PHP code, you have to run it as two queries to set the variable, then run the actual ranking query. This way, the rank variable is always set to 0 when running this. Note that I've used different table and column names, just to simplify things a little. Remember to adjust to your specific needs.
// connect to database
$conn = mysqli_connect("localhost", "user", "password", "database");
// this query will set a variable to 0.
$setSql = "SET #row_number = 0;";
// run the query. This will return a boolean - true or false, depending on whether or not the query ran successfully
$variableSet = mysqli_query($conn, $setSql);
// if the query ran successfully
if($variableSet){
// setup the actual ranking query
$statsSql = "select
(#row_number:=#row_number+1) as rank,
u.id,
u.username,
s.overall
from
mstats s
join
musers u
on
s.muser = u.id
order by
s.overall desc;";
$ranks = mysqli_query($conn, $statsSql);
if(!$ranks){
// dump error from rank query
var_dump($conn->error);
} else {
// dump results as associative array
var_dump($ranks->fetch_all(MYSQLI_ASSOC));
}
} else {
// dump errors from setting variable
var_dump($conn->error);
}
For me, the results dump looks like this:
array (size=3)
0 =>
array (size=4)
'rank' => string '1' (length=1)
'id' => string '2' (length=1)
'username' => string 'Bar' (length=3)
'overall' => string '1000' (length=4)
1 =>
array (size=4)
'rank' => string '2' (length=1)
'id' => string '6' (length=1)
'username' => string 'Tom' (length=3)
'overall' => string '7' (length=1)
2 =>
array (size=4)
'rank' => string '3' (length=1)
'id' => string '1' (length=1)
'username' => string 'Foo' (length=3)
'overall' => string '3' (length=1)
I'm trying to figure out how to make a query to get the data of top then users of some list ...later I will use php to statics and graphs but what I want is to get the sum of every single user but I find it difficult because in one month one single user can make many registers on database and I want to manage it and then get the top ten of users who have more activities (on this case with more quantity per month).
Example
user_id quantity date kind
user1 23 17/03/18 free
user1 3 17/03/18 charge
user2 5 17/03/18 free
user2 5 17/03/18 free
user2 8 18/03/18 free
user3 9 19/03/18 free
user3 1 20/03/18 free
user3 1 20/03/18 charge
user3 3 20/03/18 charge
user3 5 20/03/18 charge
You can store arrays in a database by serializing them, inserting them into the database, and then unserializing them when you retrieve from the database.
Arrays can be multidimensional in PHP, that means that arrays can store arrays and so on. Also arrays can be relational, meaning that you can store values and give an identifier ('key') to each value.
Knowing that, you can do stuff like:
$con = new mysqli($host, $username, $password, $db_name);
$stmt = $con->prepare('SELECT * FROM users WHERE user_id=?;');
$stmt->bind_param('s', $id);
$stmt->execute();
$result = $stmt->get_result()->fetch_array();
if ($array_data = unserialize($result['data'])) {
echo 'The quantity related to ', $result['name'], ' is ', $array_data['quantity'];
} else {
echo 'It seems that there\'s nothing related to ', $result['name'], ' yet. Adding a field now.';
$array_data = array(
'quantity' => 23,
'date' => date('l jS \of F Y h:i:s A'),
'kind' => 'free'
);
}
$array_data = serialize($array_data);
$stmt2 = $con->prepare('UPDATE users SET data=? WHERE user_id=?;');
$stmt2->bind_param('ss', $array_data, $id);
$stmt2->execute();
The example above is pretty abstract, but you can get a grasp of what you can do with serialization and arrays. MySQL does not have an "array" type, but you can use serialize and unserialize with almost all objects in PHP to store them in databases.
Note that the serialized fields' type in MySQL should be "BLOB".
I think that a simple count query will do the job that you want. Something like this:
Select user_id, sum(quantity) as activity-count
From ActivityTable
Group By user_id
Where kind = something; # (Optional)
I don't have so much information here about your database, so all I got is a direction for your target task.
A little test that I have run:
Table:
userid, quantity, date, kind
'0', '3', '2017-03-18', 'charge'
'0', '23', '2017-03-18', 'free'
'0', '3', '2018-03-18', 'charge'
'2', '5', '2017-03-18', 'charge'
'2', '5', '2017-03-18', 'free'
'2', '8', '2018-03-18', 'free'
'3', '9', '2019-03-18', 'free'
'3', '1', '2020-03-18', 'charge'
'3', '1', '2020-03-18', 'free'
'3', '3', '2021-03-18', 'charge'
'3', '3', '2022-03-18', 'charge'
Query:
Select userid, month(date) as 'month', sum(quantity) as activity_count
From table1
Group By userid, month(date)
Result:
userid, month, activity_count
'0', '3', '29'
'2', '3', '18'
'3', '3', '17'
This query should return you the list of top 10 users for the month:
select user_id, SUM(quantity) as qty
from table_name
group by user_id
where MONTH(CURDATE())= MONTH(date) AND
YEAR(CURRENT_DATE()) = YEAR(date)
Order by qty DESC
LIMIT 0,10;
I'm trying what seems to be a simple union query for two tables in my database though I am unable to retrieve a successful array result. It should be noted that each table has different columns and that I'd like to create a virtual result (promo AS origin [for the result pulled from the 'venpromo' table] && vacation AS origin [for the result pulled from the 'vacation' table]) in order to sort the results into different array structures. I've looked everywhere and UNIONS are all using different syntax. Thank you all in advance!
<?php
require_once('includes/config.php');
$event_query = "SELECT *, promo AS origin FROM venpromo
UNION
SELECT *, vacation AS origin FROM venpromo
ORDER BY popularity DESC";
$event_result = mysql_query($event_query, $connection);
while ($event = mysql_fetch_array($event_result)) {
if ($event['origin'] == "promo") {
$event_array[] = array(
'id' => $event['id'],
'title' => $event['calname'],
'start' => $event['sdate'],
'end' => $event['edate'],
'color' => "red",
'url' => "http://www.norrisportal.com/bulletinpost.php?id=" . $event['id'] . "&hashkey=akdULjsjyUpYyTzOT7"
);
} elseif ($event['origin'] == "vacation") {
$event_array[] = array(
'id' => $event['id'],
'title' => $event['reason'],
'start' => $event['vacstart'],
'end' => $event['vacend'],
'color' => "blue"
);
}
}
echo json_encode($event_array);
?>
When visiting the page to view the results, I see 'null'.
Put the columns names explicitly rather than *, and make sure the number of columns and data types match for the same column in each select.
I have added some dummy columns to match the number and data types in both the tables and also changed the order of the columns.
try this sample way ::
select
id,
uid,
approval,
vacstart,
vacend,
reason,
'dummy1' col1,
'dummy2' col2,
'dummy3' col3,
curdate() col4,
'dummy4' col5,
'dummy5' col6,
'dummy6' col7,
'dummy7' col8,
promo AS origin
from vacation
union
select
id,
venid,
authid,
sdate,
edate,
authname,
tags,
title,
calname,
date,
intro,
body,
sum,
sortdate,
vacation AS origin
from venpromo;
Continuing this question,
in my web app, I want to allow users to add friends, like facebook, in my previous question, I finally decided to have the database structure as #yiding said:
I would de-normalize the relation such that it's symmetric. That is,
if 1 and 2 are friends, i'd have two rows (1,2) and (2,1).
The disadvantage is that it's twice the size, and you have to do 2
writes when forming and breaking friendships. The advantage is all
your read queries are simpler. This is probably a good trade-off
because most of the time you are reading instead of writing.
This has the added advantage that if you eventually outgrow one
database and decide to do user-sharding, you don't have to traverse
every other db shard to find out who a person's friends are.
So, now if user 1 adds user 2, and user 5 adds 2, something like this will go into the db:
ROW_ID USER_ID FRIEND_ID STATUS
1 1 2 0
2 2 1 0
3 5 2 0
4 2 5 0
As you see, we insert the row of the "REQUEST SENDER" first, so now imagine that user 5 is logged in, and we want to show him the friendship requests, here is my query:
$check_requests = mysql_query("SELECT * FROM friends_tbl WHERE FRIEND_ID = '5'");
the above query, will fetch ROW_ID = 4, this means with the above query shows us that user 2 has added 5, but he has NOT, actually the user 5 added user 2, so here we should not show any friendship requests for user 5, instead we need to show it for user 2.
How I'm supposed to check this correctly?
This is an edited answer.
Your SQL query should look like this:
SELECT USER_ID, FRIEND_ID FROM friends_tbl WHERE FRIEND_ID = '5' OR USER_ID = '5'
Then you have to parse your result in this way. Assuming you have got a php array like this:
$result = array(
0 => array(
'USER_ID' => 5,
'FRIEND_ID' => 2
),
1 => array(
'USER_ID' => 2,
'FRIEND_ID' => 5
)
2 => array(
'USER_ID' => 5,
'FRIEND_ID' => 8
),
3 => array(
'USER_ID' => 8,
'FRIEND_ID' => 5
)
)
You just have to get the even rows:
$result_final = array();
for($i = 0; $i < count($result); $i++) {
if($i % 2 == 0) $result_final[] = $result[$i];
}
Then you will have an array like this:
$result = array(
0 => array(
'USER_ID' => 5,
'FRIEND_ID' => 2
),
1 => array(
'USER_ID' => 5,
'FRIEND_ID' => 8
)
)
Alternative method: Make your SQL look like this:
SELECT FRIEND_ID FROM friends_tbl WHERE USER_ID = '5'
That's all.
Friendship query notifies should be placed in something like message inbox. Relation you described is meant to hold, well, friendship relations, not the fact of the event happening itself. You should consider create relation to hold notifies and fill it properly alongside with two inserts on friends_tbl
You'll need to hold a temporary table (or fixed - for data mining) which has all the requests made from one user to another, for example:
table: friendRequest
inviterId inviteeId status tstamp
2 5 0 NOW()
5 8 0 NOW()
assuming that 0 is unapproved.
Than you'll query for all pending requests
SELECT * FROM friendRequest WHERE invitee_id = :currentLoggedUserId AND status = 0
Once a user approved a user, you'll create a transaction, describing this newly formed relation and updating the friendRequests table
You could also query this way assymetric relations, where a user has many followers, by looking for un-mutual friendships.