I need to display in alphabetical order a list of name and surname (order by surname).
The problem is I can't do a ORDER BY in SQL query because I retrieve my users ID in one table and retrieve the informations in another table.
My PHP code:
$sql = "select id FROM $table_name";
$result = $wpdb->get_results($sql);
foreach ($result as $record) {
$id = $record->id;
$sql2 = "select field_name, field_val FROM $table_name2 where sub_id = $id";
$result2 = $wpdb->get_results($sql2);
foreach ($result2 as $record2) {
if($record2->field_name == "Nom :") {
$surname = ucfirst(stripslashes($record2->field_val));
}
if($record2->field_name == "Prénom :") {
$name = ucfirst(stripslashes($record2->field_val));
}
}
echo $name . " " . $surname . "<br/>";
}
Here the architecture of the second table:
f_id sub_id field_name field_val
127 19 Prénom : Philippe
128 19 Nom : Nailloux
129 20 Prénom : John
130 20 Nom : Drumond
Have you an idea how I can display my list ordered by surname alphabetically?
Thanks.
You can do the trick by using this SQL query :
SELECT t1.id AS user_id,
t2.field_val AS surname,
t3.field_val AS name
FROM $table_name t1
JOIN $table_name2 AS t2
ON ( t2.sub_id = t1.id
AND t2.field_name = 'Nom :' )
JOIN $table_name2 AS t3
ON ( t3.sub_id = t1.id
AND t3.field_name = 'Prénom :' )
ORDER BY t2.field_val
The query will return all the infos needed (user_id, surname and name) ordered by surname.
Use subqueries!
In your example, let's say you have 100 users.
In first query you get your users ids, then for each user you query database for one's data. That's 101 queries for a simple operation! What if you have 10 visits per seconds? That's more than 1000 queries.
There are many strategies (subquery, join, two queries with in () in second one) but in this case consider that:
SELECT
field_name, field_val
FROM
$table_name2
WHERE
sub_id IN(
SELECT
id
FROM
$table_name
) as sq1
ORDER BY field_val ASC;
Also consider using PHP PDO, or at least proper escaping of data you put in queries.
Related
I have 2 tables - users and articles.
users:
user_id (int)
name (varchar)
articles:
article_id (int)
user_id (int)
title (varchar)
description (text)
In my application I need to display 20 RANDOM articles on a page.
My query is like this:
SELECT a.title
, a.description
, u.name
FROM articles a
JOIN users u
USING (user_id)
ORDER
BY RAND()
LIMIT 20
A user can have any number of articles in the database.
Now the problem is sometimes out of 20 results, there are like 9-10 articles from one single user.
I want those 20 records on the page to not contain more than 3 (or say 4) articles from a particular user.
Can I achieve this through SQL query. I am using PHP and MySQL.
Thanks for your help.
You could try this?
SELECT * FROM
(
SELECT B.* FROM
(
SELECT A.*, ROW_NUMBER() OVER (PARTITION BY A.USER_ID ORDER BY A.R) USER_ROW_NUMBER
FROM
(
SELECT a.title, a.description, u.name, RND() r FROM articles a
INNER JOIN users u USING (user_id)
) A
) B
WHERE B.USER_ROW_NUMBER<=4
) C
ORDER BY RAND() LIMIT 20
Mmm, intresting I don't think this is possible through a pure sql query.
My best idea would be to have an array of the articles that you'll eventually display query the database and use the standard SELECT * FROM Articles ORDER BY RAND() LIMIT 20
The go through them, making sure that you have indeed got 20 articles and no one has breached the rules of 3/4 per user.
Have another array of users to exclude, perhaps using their user id as an index and value of a count.
As you go through add them to your final array, if you find any user that hits you rule add them to the array.
Keep running the random query, excluding users and articles until you hit your desired amount.
Let me try some code (it's been a while since I did php)
$finalArray = [];
$userArray = [];
while(count($finalArray) < 20) {
$query = "SELECT * FROM Articles ";
if(count($finalArray) > 0) {
$query = $query . " WHERE articleID NOT IN(".$finalArray.")";
$query = $query . " AND userID NOT IN (".$userArray.filter(>4).")";
}
$query = $query . " ORDER BY Rand()";
$result = mysql_query($query);
foreach($row = mysql_fetch_array($result)) {
if(in_array($finalArray,$row) == false) {
$finalArray[] = $row;
}
if(in_array($userArray,$row[userId]) == false) {
$userArray[$row[userId]] = 1;
}
else {
$userArray[$row[userId]] = $userArray[$row[userId]] + 1;
}
}
table1:
id (autoincrement)
username
category
table2:
id (autoincrement)
itemname
category
I have 2 queries.
1 query one shows categories that a user (logged in) belongs to:
$sql = "SELECT * FROM table1 WHERE '$login_session' = username";
I can list each record:
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo "category: " . $row["category"]. "<br>";
}
That works fine.
My 2nd query is dependent on the 1st query. I need to list all records from table2 where category belongs to in array category in previous query.
$sql2 = "SELECT * FROM table2 WHERE category = I DO NOT KNOW WHAT TO PUT HERE";
How do I write $sql2?
One method uses in:
SELECT *
FROM table2
WHERE category IN (SELECT category FROM table1 WHERE '$login_session' = username");
You can use IN()
$sql = 'SELECT * FROM table2 WHERE category IN ('"' . implode('","', $arrayOfCategories).'"')'
I'm new to programming and would really appreciate your help. :) So, I have a USER table and a SALES table. On the SALES table I only have name and last name of the users. On the USER table I have name, last name, USER_ID, email and etc...
I need to copy the USER_ID from the USER table to the SALES table when NAME and LAST NAME are a match.
Here is the structure:
USER_TABLE_A
USER_ID_A
NAME_LASTNAME_A
SALES_TABLE_B
ROW_ID_B
NAME_B
LASTNAME_B
USER_ID_B (empty)
So far I got both tables to show data when they intersect but have no idea where to go from here. Could anyone please help?
$sql1 = mysql_query("SELECT name_B, lastname_B, user_id_B, row_id_B FROM sales_table_B WHERE name_B IS NOT NULL AND lastname_B IS NOT NULL", $db);
$sql2 = mysql_query("SELECT name_lastname_A, user_id_A FROM user_table_A WHERE name_lastname_A IS NOT NULL", $db);
$a1 = array();
while ($row = mysql_fetch_array($sql1)) {
$id = $row['row_id_B'];
$name1.$id = $row['name_B']." ".$row['lastname_B'];
array_push($a1, $name1.$id);
}
$a2 = array();
while ($row2 = mysql_fetch_array($sql2)) {
$id2 = $row2['user_id_A'];
$name2.$id2 = $row2['name_lastname_A'];
array_push($a2, $name2.$id2);
}
$result = array_intersect($a1,$a2);
print_r($result);
Thanks in Advance!
Under the assumption that NAME_LASTNAME_A column in USER_TABLE_A is a concatenation of NAME_B and LASTNAME_B columns of SALES_TABLE_B, following UPDATE query should update the ids:
update sales_table_b
set b.user_id_b = (
select user_id_a from user_table_a
where name_lastname_a = concat(b.name_b, ' ' , b.lastname_b)
limit 1
where exists(
select user_id_a from user_table_a
where name_lastname_a = concat(b.name_b, ' ' , b.lastname_b)
)
)
Please note that in case of multiple users having same first and last name, id of the first matching user will be considered.
Thank you so much Darshan!! Your answer was missing a ) after limit 1 but with the adjustment it worked beautifully! Here is the code that worked:
UPDATE sales_table_b
SET user_id_b = (SELECT user_table_a.user_id_a
FROM user_table_a
WHERE user_table_a.name_lastname_a = CONCAT(sales_table_b.name_b, ' ' , sales_table_b.lastname_b) LIMIT 1)
WHERE EXISTS (SELECT *
FROM user_table_a
WHERE user_table_a.name_lastname_a = CONCAT(sales_table_b.name_b, ' ' , sales_table_b.lastname_b))
I have a database structure something like the following:
Table A: PersonId, GroupId
Table B: GroupId, ParentGroupId
Given a PersonId, I want to find the Ids of all people in parent groups of that person's group.
First I select the ParentGroupId for the given PersonId, by joining with B. Then I do a while loop, selecting and recording the PersonId from A based on the GroupId returned in the previous search, and continue the loop by obtaining the next ParentGroupId from B.
Is this an efficient way to do this search, or is there an option that does not involve a while to "bubble up" in this manner?
(this is a simplified version of the actual scenario, changing the schema is not an option)
$sql = 'SELECT ParentGroupID FROM A WHERE PersonId = ' . $id;
$result = $db->query($sql);
$row = $db->fetch_array($result);
$parent_group = $row['ParentGroupId'];
if(!is_null($parent_group)) {
$parent_ids = array();
while($parent_group > 0) {
//is there a way to do this where I retrieve all managers <= lvl 6 at once, so I don't have to loop in order to 'tier up'?
$sql = 'SELECT ParentGroupID, PersonID
FROM B
INNER JOIN A on ParentGroupID = A.GroupID
WHERE ParentGroupID = ' . $parent_group;
$result = $db->query($sql);
$row = $db->fetch_array($result);
$parent_group = $row['ParentGroupID'];
$parent_ids[] = $row['PersonID'];
}
}
Combining your two queries into one would be more efficient:
$sql = 'SELECT ParentGroupID, PersonID
FROM B
INNER JOIN A on ParentGroupID = A.GroupID
WHERE ParentGroupID IN (
SELECT ParentGroupID FROM A WHERE ParentGroupID > 0
AND PersonId = ' . $id .')' ;
Mysql query and PHP code that I'm using to get users from the database that meet certain criteria is:
$sql = mysql_query("SELECT a2.id, a2.name FROM members a2 JOIN room f ON f.myid = a2.id
WHERE f.user = 1 AND a2.status ='7' UNION SELECT a2.id, a2.name FROM members a2
JOIN room f ON f.user = a2.id WHERE f.myid = 1 AND a2.status ='7' GROUP BY id")
or die(mysql_error());
while ($r = mysql_fetch_array($sql))
{
$temp[] = '"'.$r[0].'"';
}
$thelist = implode(",",$temp);
The query that follows get the list of members with new galleries by using array from the previous query.
$ft = mysql_query("SELECT id, pic1 FROM foto WHERE id IN ($thelist) AND
pic1!='' ORDER BY date DESC LIMIT 10");
while ($f = mysql_fetch_array($ft))
{
echo $f['id']." - ".$f['pic1']."<br/>";
}
These queries working fine but I need to get the name for every user listed in second query. This data is in the first query in the column name. How can I get it listed beside '$f['id']." - ".$f['pic1']'?
While I might just alter the first query to pull the galleries at the same time, or change the second query to join and get the name, you could keep the same structure and change a few things:
In the loop after the first query when building $temp[], also build a lookup table of user id to user name:
$usernames[$r[0]] = $r[1];
Then in your output loop, use the id (assuming they are the same!) from the second query to call up the user name value you stored:
echo $f['id'] . " - " . $f['pic1'] . " - " . $usernames[$f['id']] . "<br/>";