MySQL order By issue - php

Hi simple question i guess, but cant figure out how to list the mysql sql the way i want it.
Basiclly in one row I have CityID's I want to be able to pull out the CityID's that == 14 and show them at the top of the return (BUT NOT AS A COUNT)
for e.g
Perth == 15
Melbourne == 14
Preston == 14
Sydney == 13
currently they show like this
Sydney == 13
Perth == 15
Melbourne == 14
Preston == 14
my code
$sth = mysql_query("SELECT users.id as id, users.username as username, profile.defaultpictureid as picture FROM users, userprofiles as profile WHERE online = '1' AND profile.country = ".$this->country." AND profile.state = ".$this->state." AND profile.city = ".$this->city." ORDER BY if (profile.city = 12276,0,1)");
The code above seems to be working now.
However also seems to print out the data twice.
[{"id":"7","username":"A","picture":"0"},{"id":"1","username":"B","picture":"0"},{"id":"1","username":"B","picture":"1"},{"id":"7","username":"A","picture":"1"}]

You're selecting from two tables (users and profiles), but have no specified any kind of relationship between when in your where clause, so what you're getting is the Cartesian product of the two, which is why you're getting the duplicated results.
I'm guessing your query should look something more like this:
SELECT users.id as id, users.username as username, profile.defaultpictureid as picture
FROM users, userprofiles as profile
WHERE
online = 1 AND
profile.country = {$this->country} AND
profile.state = {$this->state} AND
profile.city = {$this->city} AND
users.id = userprofiles.userid <---the join condition for the two tables
ORDER BY if (CityID = 14, 1, 0), profile.city

You can apply an if clause in the sorting
order by if(CityID = 14,0,1)

Related

Mysql UNION ALL to count multiple columns BUT also insert date column

Hi Guys I have a question. I am still learning and am trying to get some date out. Beneath is the table. It has hundreds of lines, but for example:
FormNR
Datum
XX1
XX2
XX3
0001
2022-09-08
4
23
7
0002
2022-09-10
8
5
0
The table name is 'forms'. Now what I need to do is to count XX1+XX2+XX3 (for a year rapport). Then I have a 'date from and to' selection box on my page. So the question would be:
What instanties have been used between a certain date in total but so that you can see a a total per Instantie (each number is a different instantie).
So for example...Between the 1st of January and the 1st of June a list of all XX numbers ( there are 36 ) with there total behind it
What I have is the following. Is works great and shows all XX's in a nice table but for the entire table, not per date. As soon as i want to add the 'between $date_from AND $date_to' it fails.
<?php
$sql_rg_total="SELECT forms.Datum, x.f1,Count(x.f1)
FROM
(SELECT XX1 As F1 FROM forms
UNION ALL
SELECT XX2 As F1 FROM forms
UNION ALL
SELECT XX3 As F1 FROM forms) x
WHERE x.f1 = '$subcat_id'
GROUP BY x.f1";
$resultvv=mysqli_query($conn, $sql_rg_total);
if (mysqli_num_rows($resultvv) > 0) {
while ($rowvv = mysqli_fetch_assoc($resultvv)) {
$subnr = $rowvv['Count(x.f1)'];
echo $subnr;
}
}
?>
By the way $subcat_id is from another table which connects the number to a name.
I have tried to write it as clear as I could. I know it's a bit thought haha. Thanks anyway for any input. Really stuck.
This query should do it:
SELECT SUM(x.c) AS c
FROM (
SELECT ((XX1 = '$subcat_id') + (XX2 = '$subcat_id') + (XX3 = '$subcat_id')) AS c
FROM forms
WHERE Datum BETWEEN '$date_from' AND '$date_to'
) x
The value of a boolean condition is 1 when it's true, 0 when it's false. So XX1 = '$subcat_id' + XX2 = '$subcat_id' + XX3 = '$subcat_id' adds up the number of columns that match in a row, then SUM(c) totals them in the entire table.
You don't need GROUP BY, since it's the same column that you're filtering in the WHERE condition (and now in the SELECT expression). And this moves the date condition into the subquery.

Count total Average rating with PHP

How would I go about running a PDO query and then processing the results with PHP to output an Average rating for a specific blank based on user inputted reviews?
Each review is weighted on 2 criterias, Service and Price. Both of this are 0-5 therefore the end average is weighted out of 10. Per review bases I currently use the following code to calculate the Average Rating for the specific review.
$rating_total = $row['review_service_rating'] + $row['review_price_rating'];
$average_rating = ($rating_total / 100) * 100;
So for each review there are 2 sql rows for review_service_rating and review_price_rating both of this are out of 5.
However I'm not exactly sure how to Count all of the ratings and then determine base grade for the specific page out of 10.
So let's say we have 3 reviews. This reviews are 7/10, 8/10 and 10/10. Logically we would add up all of the numbers and then add up all of /10 giving us. 25/30 which translates to 83.33 or in my case 8/10. This are the 2 steps I'm uncertain how to do.
1 - Get all ratings from SQL and count them
2 - Determine Average /10 based on all ratings
Current PDO code to pull data from DB as well as Count of how many Reviews each particular user has.
$q = $db->prepare("SELECT * FROM reviews WHERE assigned_id = :review_id ORDER BY review_posted DESC");
$q->execute(array(':review_id' => $_GET['page_id']));
$r = $q->fetchAll(PDO::FETCH_ASSOC);
echo '<br><div class="well">Average Rating</div><br>';
foreach($r as $row) {
$q = $db->prepare("SELECT * FROM users WHERE user_id = :review_user_id");
$q->execute(array(':review_user_id' => $row['user_id']));
$r = $q->fetch(PDO::FETCH_ASSOC);
$q = $db->prepare("SELECT COUNT(*) FROM reviews WHERE user_id = :review_user_id");
$q->execute(array(':review_user_id' => $row['user_id']));
$user_reviews = $q->fetchColumn();
Assume each user give x point (limit by 10), you must sum them up (x) then divide it by rating_times, you get average rating.
For example
User 1 rate 7
User 2 rate 6
User 1 rate 5
=> (7+6+5)/3 = 6
So you just add one more field when user rating called point.
Then use query SUM to SUM point up, divided with query COUNT then done.
forget the (x**/10**).
Finally, use 2 average rating (Price and service), sum of them, divided by 2 and you got overall rating.
Here's what you probably meant to do:
$q = $db->prepare("
SELECT *
FROM review r
JOIN users u ON r.user_id=u.id
JOIN (SELECT user_id, COUNT(1) as count FROM review GROUP BY user_id) uc ON uc.user_id = u.id
WHERE r.assigned_id=:review_id
ORDER BY r.review_posted DESC");
$q->execute(array(':review_id' => $_GET['page_id']));
$r = $q->fetchAll(PDO::FETCH_ASSOC);
foreach ($r as $row) {
// $row should have all fields included in $tables review and users as well as $row[count] would contain the total number of reviews a user made
}
This will include the user's details alongside the rating details for each review with that assigned_id
Edit: Added sum of user reviews as well.
You can use this snippet.
This helped me
https://gist.github.com/tiagofrancafernandes/1c5752ba2ebeb477975c6c016a37fc5c

MySQL count datas with row values without new query loop

I've 4 table for a newsletter. Newsletters, Subscribers, Subscriber Groups and Selected Subscriber Groups. I've choose subscriber groups in campaign edit area, and its save selected groups to tbl_newsletter_groups table like;
tbl_newsletters
NID title details
1 text 1 content 1
2 text 2 content 2
tbl_subscriber_groups
GID group_name
5 group 1
6 group 2
tbl_subscribers
SID GID email name
10 5 sub1#mail.com sub1 name
11 6 sub1#mail.com sub1 name
tbl_newsletter_groups
NGID NID GID
15 1 6
16 1 6
17 1 6
I want to show total selected subscriber count when I list newsletters in my page. My soulution works fine, Im looking for simple and clearly statement, there any faster way available like in single newsletter list statement?
Here my own count style (yes I know its too bad and long way);
$subGID = array();
$list = $myconn->query("SELECT * FROM tbl_newsletters");
while($listRs = $list->fetch_assoc()){
$grps = $myconn->query("SELECT * FROM tbl_newsletter_groups WHERE NID=". $listRs['NID'] ."");
while($grpsRs = $grps->fetch_asscoc()){
$subGID[] = $grpsRs['GID'];
} $grps->free();
$subs = implode(" OR GID=",$subGID);
$count = mysqli_num_rows($myconn->query("SELECT ID FROM tbl_subscribers WHERE GID=". $subs));
echo('Total Selected Subscriber: '.$count);
} $list->free();
Thanks.
The search term you want is "set-based logic".
Your thinking is sound: you need everything from tbl_newsletters, then you need to count results from tbl_subscribers, but in order to get those you need information from tbl_newsletter_groups.
In SQL, that's an indication you want a join. You've already discovered the conditions you need, you just don't know the syntax. A reference manual can help there.
Now you'll have a bunch of records, which you need to smash into a smaller number of records. You need aggregation functions and a GROUP BY clause.
So here's the final query:
SELECT n.NID, n.title, n.details, COUNT(s.SID)
FROM tbl_newsletters AS n
JOIN tbl_newsletter_groups AS g ON n.NID = g.NID
JOIN tbl_subscribers AS s ON g.GID = s.GID
GROUP BY n.NID

accessing parts of sub-queries to build HTML in a PHP server

I have a query that returns the count of active and inactive posts, plus the specific post details. Here's the query
$fetch = mysql_query("SELECT SQL_CALC_FOUND_ROWS * FROM
(SELECT DISTINCT propertyID, streetAddress, city FROM residence.property
WHERE residence.contact.contactEmailAddress1 ='$contactEmailAddress1' AND activePosting = '0') inactposts,
(SELECT FOUND_ROWS() AS 'inactiveCount') inact,
(SELECT DISTINCT propertyID, streetAddress, city FROM residence.property
INNER JOIN contact ON residence.contact.ContactID = residence.property.ContactID
WHERE residence.contact.contactEmailAddress1 ='$contactEmailAddress1' AND activePosting = '1') actposts,
(SELECT FOUND_ROWS() AS 'activeCount') act;")
or die('<li class=error>Ooops</li>'.mysql_error());
The query works in my web page. In MySQL Workbench it returns things looking like:
propID address city inactCount propID address city actCount
366 110 Main Street Perinton 1 352 3 Some Place Perinton 3
366 110 Main Street Perinton 1 353 5 Joe Place Perinton 3
366 110 Main Street Perinton 1 356 111 Main Perinton 3
The issue for me is the 2 parts of the sub-query results don't have an identifier (that I can find), so in the HTML constructed by the PHP server, I can't separate the lists into into inactive posts (inactposts) and active posts (actposts). Currently the HTML only returns the list of active posts. I've tried putting "inactposts", the name of the temporary table, in various places and I just get error messages
Here's the PHP doing the HTML construction:
if( mysql_num_rows($fetch) ) {
while ($row = mysql_fetch_array($fetch)) {
$inactiveCount = $row["inactiveCount"];
$activeCount = $row["activeCount"];
$storedStreetAddress = $row["streetAddress"];
$storedCity3 = $row['city3'];
$error_NumberInactives = "<ul>You have $activeCount active posts and $inactiveCount inactive posts.</ul>";
$error_List_Actives = "<li>Your $activeCount active posts are:</li>";
$errorMessages[0] = $error_NumberInactives;
$errorMessages[1] = $error_List_Actives;
$errorMessages[] = "<li> $storedStreetAddress, $storedCity3 </li>";
}else{ //error message}
How can I construct separate lists of sub-query results from this query? Or do I need a different query?
You'll need another query without the aggregation if you want the individual rows.
Alternately, select all of the posts (with details) in one query and parse the result in php to count the number of active and inactive:
SELECT DISTINCT propertyID, streetAddress, city, activePosting FROM residence.property
INNER JOIN contact ON residence.contact.ContactID = residence.property.ContactID
WHERE residence.contact.contactEmailAddress1 ='$contactEmailAddress1'
p.s. I assume you have sanitized your inputs outside of the provided code, otherwise you need to do that.

Creating a mysql query syntax with JOINING tables

I'm having trouble getting some data.... I was wondering if someone can help me,
I have 4 tables (likes, follow, comment, users)
I want to be able to populate my page when a user likes/comments/follows/etc... (if a user is following a particular user).
likes
idlikes idusers iditem
1 1 5
2 2 4
3 2 22
follow
idfollow idusers_follower idusers idbusiness
1 1 2
2 1 3
3 1 4
4 4 2
5 4 1
comment
idcomments idusers text
1 1 asfd
2 2 safd
users
idusers
1
2
3
4
For example if I am id user #1, I'm following users #2, #3, #4
My page would populate to show:
#2 likes item #4, #22.
#4 is following #2 (because I'm following #4, this is why its showing)
#2 comments "safd"
I'm not sure what is the best way to display this? I currently have multiple functions querying on table at a time, and I'm working on merging the arrays together? Or should I use join tables? Which I'm trying now...
Get users that I'm following.
$feeds = new feed();
$meID = 1;
$query = "SELECT idusers FROM follow WHERE iduserse_follower = ?";
$users = $dbh -> prepare($query);
$users -> execute(array($meID));
while($following = $users -> fetch(PDO::FETCH_ASSOC)){
$follow = $following['idusers']; //This will get all of useres I'm following
$populate = $feeds->feed_all($follow); // from function
}
Query
class feed()
{
public function feed_all($idusers)
{
// SYNTAX HELP //////////////////////
$query = "SELECT
f.idusers_follower,
f.idusers,
l.iditem,
c.text
FROM follow f, users u
JOIN likes l
ON l.idusers = f.idusers
JOIN comment c
ON c.idusers = f.idusers
WHERE f.idusers_follower = ? AND f.idusers_follower = l.idusers AND f.idusers_follower = c.idusers AND f.idusers = u.idusers"
$pop = $dbh->prepare($query);
$pop ->execute($idusers);
// while loop to return value
while($row = $pop -> fetch(PDO::FETCH_ASSOC))
{
$feed_data[]=$row;
}
return $feed_data;
}
}
This is where I'm stuck. :( I'm not even sure if I'm doing the statement right?
++++++++++ EDIT: ++++++++++++
I have edited to add idbusiness
Now since I'm following #4, it would also show up that #4 is following #1.
Your current approach of performing three separate queries is as good as any; you can combine them into a single resultset using UNION, which would be useful if you wanted to sort the combined results by some field (e.g. activity timestamp) and/or limit the combined results:
SELECT idusers, 'likes' AS what, likes.iditem AS detail
FROM likes JOIN follow USING (idusers)
WHERE follow.idusers_follower = 1
UNION ALL
SELECT f1.idusers, 'follows', f2.idusers
FROM follow f1 JOIN follow f2 ON f1.idusers = f2.idusers_follower
WHERE f1.idusers_follower = 1
UNION ALL
SELECT idusers, 'commented', comment.text
FROM comment JOIN follow USING (idusers)
WHERE follow.idusers_follower = 1
See it on sqlfiddle.

Categories