Combine several SQL querys to one - php

I know this is probably really simple but I have tried to find some similar examples and failed.
The problem is that I would like to list 8 random images from a gallery in a database, sorted by added date. And I have managed to do this, but only with several iterating query's that becomes really slow. So if someone would be so kind to teach me about combining them for faster speed, I guess UNION is the way to go? Here is my working (but slooow code)
<?php
$latestPictures = mysql_query("SELECT pictureID, addedDate FROM picture ORDER BY addedDate DESC LIMIT 8");
$latestConcerts = mysql_query("SELECT concertID, addedDate FROM concert WHERE pictureID is null ORDER BY addedDate DESC LIMIT 8");
// Add concerts and pictures to array
while($curFestival = mysql_fetch_object($latestPictures))
{
$array[$curFestival->addedDate] = "p" . $curFestival->pictureID;
}
while($curConcert = mysql_fetch_object($latestConcerts))
{
$array[$curConcert->addedDate] = "c" . $curConcert->concertID;
}
// Order array by key
krsort($array);
$latestArray = array_slice($array, 0, 8);
foreach($latestArray as $key => $value) {
$type = substr($value, 0, 1);
$ID = substr($value, 1);
// If type == picture
if($type == 'p')
{
$picturesPicturesID = mysql_query("SELECT concertID, name FROM photo WHERE concertID IN(SELECT concertID FROM concert WHERE pictureID = $ID) ORDER BY photoID");
// Get random picture
$curRandomPicture = rand(0, (mysql_num_rows($picturesPicturesID) - 1));
$curPictureConcertID = mysql_result($picturesPicturesID, $curRandomPicture, "concertID");
$curPictureName = mysql_result($picturesPicturesID, $curRandomPicture, "name");
$curPicture = mysql_fetch_object(mysql_query("SELECT c.URL, p.name FROM concert c, picture p WHERE p.pictureID = c.pictureID AND c.concertID = $curPictureConcertID"));
echo "Some image";
}
// If type == concert
if($type == 'c')
{
$concertPicturesID = mysql_query("SELECT concertID, name FROM photo WHERE concertID = $ID ORDER BY photoID");
// Get random picture
$curRandomPicture = rand(0, (mysql_num_rows($concertPicturesID) - 1));
$curPictureConcertID = mysql_result($concertPicturesID, $curRandomPicture, "concertID");
$curPictureName = mysql_result($concertPicturesID, $curRandomPicture, "name");
$curPicture = mysql_fetch_object(mysql_query("SELECT URL, name FROM concert WHERE concertID = $curPictureConcertID"));
echo "Some image";
}
}
?>
I realized that I forgot to include the tables, here they are:
TABLE OF photo:
PKEY: photoID
FKEY: concertID
name
TABLE OF concert:
PKEY: concertID
FKEY: pictureID
name
URL
addedDate
TABLE OF picture
PKEY: pictureID
name
date
So every post is part of TABLE photo AND concert, but only some is part of picture witch is only used sometimes to group differens albums together. When they are grouped together I whant a random name post from that grouping ID (picture) and if they are by them self a random name post from there (concert).

Accckkk! (In the infamous words of Bill the Cat.)
It's hard to figure out what result set your code really wants from the database.
This query isn't the most efficient, but it will return 8 random rows from the photos table, with those rows ordered by addedDate:
SELECT r.*, c.*
FROM (SELECT p.*
FROM photo p
WHERE p.concertid IS NOT NULL
ORDER BY RAND()
LIMIT 0,8
) r
JOIN concert c
ON c.concertid = p.concertid
ORDER BY r.addedDate ASC
If you have a really large photo table, this is going to be slow, because that RAND() function has to get called for every single row in the table, and MYSQL has to produce a temporary result set (a copy of the table) and then sort it on that derived column.
(NOTE: I'm assuming here that it's the photo table that you want to return "random" rows from, and I'm assuming that concertid is the primary key on the concert table, and a foreign key from the photo table. It's apparent that you have three tables... concert, picture and photo, but it's not clear which columns are the primary keys and which columns are the foreign keys, so it's likely I have it wrong.)
(NOTE: replace the p.* and c.* with a list of expressions you actually want to return.)
There are more efficient approaches to returning a single random row. In your case, you want exactly eight rows, and you presumably don't want to return a duplicate.

Related

PHP, SQL - getting fetch where table id = user id and count other table where row is = user id

Thanks for helping, first I will show code:
$dotaz = "Select * from customers JOIN contracts where customers.user_id ='".$_SESSION['user_id']."' and contracts.customer_contract = ".$_SESSION['user_id']." order by COUNT(contracts.customer_contract) DESC limit $limit, $pocetZaznamu ";
I need to get the lists of users (customers table) ordered by count of contracts(contracts table)
I tried to solve this by searching over there, but I can't... if you help me please and explain how it works, thank you! :) $pocetZanamu is Number of records.
I need get users (name, surname etc...) from table customers, ordered by number of contracts in contracts table, where is contract_id, customer_contract (user id)..
This should do it where is the column name you are counting.
$id = $_SESSION['user_id'] ;
$dotaz = "Select COUNT(`customer_contract`) AS CNT, `customer_contract` FROM `contracts` WHERE `user_id`=$id GROUP BY `customer_contract` ORDER BY `CNT` DESC";
Depending on what you are doing you may want to store the results in an array, then process each element in the array separately.
while ($row = mysqli_fetch_array($results, MYSQL_NUM)){
$contracts[$row[1]] = $row[0];
}
foreach ($contracts AS $customer_contract => $count){
Process each user id code here
}
Not sure what you are counting. The above counts the customer_contract for a table with multiple records containing the same value in the customer_contract column.
If you just want the total number of records with the same user_id then you'd use:
$dotaz = "Select 1 FROM `contracts` WHERE `user_id`=$id";
$results = $mysqli->query($dotaz);
$count = mysql_num_rows($results);

Codeigniter / PHP, 2 Mysql Tables, Multiple Queries

I have 3 tables 1 is an item table, one is a note table and the other is a note image table.
When a user views item details, all notes are picked up for that item (there is a item_id field in the note table)
The notes can have multiple images attached to them these are stored in flat file but are referenced by the "note image" table.
Now when displaying item details I run a query to get all notes for a item... simple enough, then these results are looped through to output them onto the page.
Problem now arises after adding images to notes, how would you go about querying all notes for a item say
SELECT * FROM notes WHERE item = 1
then how would you loop though the result array getting all note images for a note say
SELECT * FROM note_img WHERE note_img_noteid = 27
Its hurting my head a little because I can't visualize how to get the results and output them in PHP.
---EDIT---
Think I may of got it,
SELECT
d.door_note_id,
d.door_note_doorid,
d.door_note_timestamp,
d.door_note_editedtime,
d.door_note_text,
u.user_name AS created_by,
e.user_name AS edited_by,
i.door_img_id AS img_id,
i.door_img_url AS img_url
FROM
user u,
door_note d
LEFT JOIN
user e
ON
user_id = d.door_note_editeduserid
LEFT JOIN
door_img i
ON
door_img_noteid = d.door_note_id
WHERE
d.door_note_doorid = 214
AND
u.user_id = d.door_note_userid
Then I use this:
foreach ($result->result() as $row){
if(!isset($my_items[$row->door_note_id])){ //the note id becaoms a key
//here you set up an array for all the note details
$my_items[$row->door_note_id] = array('door_note_id'=>$row->door_note_id,
'door_note_doorid'=>$row->door_note_doorid,
'door_note_timestamp'=>$row->door_note_timestamp,
'door_note_editedtime'=>$row->door_note_editedtime,
'door_note_text'=>$row->door_note_text,
'created_by'=>$row->created_by,
'edited_by'=>$row->edited_by,
'images'=>array());
}
//if the note has any images add them to the images array for that note.
if(isset($row->img_url)){
$my_items[$row->door_note_id]['images'][] = $row->img_url;
}
}
Its very hard to know when you haven't post your relationships in a table but taking some assumptions
$query = "SELECT items.id as item_id, items.name as item_name, notes.id as note_id,
notes.description as note_description, note_image.image as note_image from notes
LEFT JOIN notes ON items.id = notes.item_id
LEFT JOIN note_image ON notes.id = note_image.note_img_noteid";
//this wil fetch all you items with description, notes and images, because item can have multiple notes, your result wil have multiple entires of the item. so you have to index correctly to use in views
$result = $this->db->query($query)
$my_items = array();
foreach ($result->result() as $row){
if(!isset($my_items[$row->item_id])){ //you item it becaoms a key
//here you set up an array for all your items
$my_items[$row->item_id] = array('item_name'=>$row->item_name, 'notes'=>array());
}
//here you stroe all images fro a note
if(!isset($my_items[$row->item_id]['notes'][$row->note_id])){
$my_items[$row->item_id]['notes'][$row->note_id] = array('note_description'=>$row->note_description, 'images'=>array());
}
$my_items[$row->item_id]['notes'][$row->note_id]['images'][] = $row->note_image;
}

How to get a session value from a second table?

I have two tables for the users; a login table and the user profile table.
I want to compare a value from 'userprofiletable' to another value from another table called posts. If the value is equal, it shows a list.
I have the following code. The problem is that it is not comparing the value in the posts table with the value of the session from user profile table.
Could someone help me please?
<?php
$limit = '5';
$dbreq = 'SELECT * FROM `posts` ORDER BY `pos` DESC';
$dbdata = mysql_query($dbreq);
while($dbval = mysql_fetch_array($dbdata))
{
if (($dbval['city'] == $_SESSION['student_city'])) { //checks for last 4 accomodation
if ($limit >= '1') {
echo '<tr><td>'.$dbval['title'].'</td></tr>';
$limit = $limit -'1';
}
}
}
?>
I also want to get the value of userprofiletable and post it in the posts table. For example, when somebody make a new post.
Your post is a bit unclear, but I think this is what you want:
<?php
$userid = 11542;//Sample uid. You will have to figure this out and set it.
$limit = 5;
$dbreq = "SELECT * FROM `posts` WHERE `userid`=".$userid." ORDER BY `pos` DESC LIMIT=".$limit.";";
$dbdata = mysql_query($dbreq);
while($dbval = mysql_fetch_array($dbdata))
{
if (($dbval['city'] == $_SESSION['student_city'])) { //checks for last 4 accomodation
echo '<tr><td>'.$dbval['title'].'</td></tr>';
}
}
?>
The question is not clear, but there could be two answers:
To reproduce your code, you can do in ONE sql query:
$dbreq = 'SELECT *
FROM `posts`
WHERE city="'.mysql_real_escape_string($_SESSION['student_city']).'"
ORDER BY `pos` DESC
LIMIT 4';
If, however, there are two tables, then you need "LEFT JOIN" linking the posts table to the userprofile table
$dbreq = 'SELECT p.*, u.*
FROM posts p
LEFT JOIN userprofiletable up ON p.UserID=up.UserID
WHERE up.city="'.mysql_real_escape_string($_SESSION['student_city']).'"
ORDER BY p.pos DESC
LIMIT 4';
(UserID in the table above is the name of the field in the posts table and userprofiletable that links the two.)

MySQL query keeps doing LIMIT 1

This query here is supposed to SELECT * pages where the $_GET['variables'] match the conditions. The $_GET['variables'] are $page_type = type of page AND $loc = location to search. The problem is that I have it set to LIMIT 20, but it only renders one page.
function SearchByTypeLoc($page_type, $loc) {
$query = mysql_query("
SELECT
`$page_type`.title AS title,
`$page_type`.url_title AS url_title,
`$page_type`.page_type AS page_type,
`$page_type`.street AS street,
`$page_type`.city AS city,
`$page_type`.state AS state,
`$page_type`.city_state_zip AS city_state_zip,
`$page_type`.phone AS phone,
LEFT(`$page_type`.body, 100) AS body,
LEFT(`$page_type`.type, 50) AS type,
GROUP_CONCAT( i.image_loc ) AS images
FROM `$page_type`
JOIN page_images i USING( title )
WHERE
`$page_type`.page_type = '$page_type' AND
`$page_type`.city = '$loc'
ORDER BY title
LIMIT 20");
while($fetch = mysql_fetch_assoc($query)) { ...
?>
Any idea how to make it not LIMIT 1?
GROUP_CONCAT is an aggregate function,
try explicitly add a
GROUP BY `$page_type`.title
It doesn't LIMIT 1, but there is only $page_type which matches the criteria. You join on title (why not on an id?) so there must only be one $page_type with images with a matching title.
If you want to return pages which also may not have any images then you need to change the JOIN to LEFT JOIN.
The way you link pages to images is flawed. If you change the title of a page you need to remember and update the respective title in the images table. In any case this is not a proper foreign key. You should use an auto_increment id on pages.

Trick Question; Showing 'nr of results' of MySql search

I have a classifieds website, and users can search ads.
The results are displayed in three tabs on top of the page. These three are "All", "Private", and "Company".
Each tab has a nr attached to it, which represents the nr of ads found in that tab.
So for example:
All Private Company
5 3 2
All is just a total of private+company!
I am using MySql as a database.
I am trying to figure out a way to find out these "numbers of ads found" for each tab.
I have one way of doing this, which is like this, but gives me a headache because it is so messy:
$query = "SELECT SQL_CACHE * FROM classified WHERE classified.classified_id=$id";
if ($adtypes=="Private"){
$query_priv_comp = "SELECT SQL_CACHE * FROM classified WHERE priv_comp='Company'";
}
else {
$query_priv_comp = "SELECT SQL_CACHE * FROM classified WHERE priv_comp='Private'";
}
switch ($adtypes){
case "Private":
$query.= " AND classified.priv_comp='Private'";
break;
case "Company":
$query.= " AND classified.priv_comp='Company'";
break;
}
$qry_result = mysql_query($query); // main query
$result_priv_comp = mysql_query($query_priv_comp); // second query
$num_priv_comp = mysql_num_rows($result_priv_comp);
if ($adtypes=="All"){
$num_total = mysql_num_rows($qry_result);
}
else if ($adtypes!="All"){
$num_total=mysql_num_rows($qry_result) + mysql_num_rows($result_priv_comp);
}
if ($adtypes=="Private"){
$num_private = $num_total - $num_priv_comp;
$num_company = $num_priv_comp;
}
else {
$num_company = $num_total - $num_priv_comp;
$num_private = $num_priv_comp;
}
Do you know of any other way which this can be done?
Thanks
BTW: I need the rows too, in order to display information to the user of the ads found!
It depends on what you need exactly. If you just need the counts it's relatively easy:
SELECT count(*) count_all
, sum(if(priv_com = 'Private', 1, 0)) count_private
, sum(if(priv_com = 'Company', 1, 0)) count_company
FROM classified
WHERE classified.classified_id=$id
If on the other hand, you need both counts as well as row data, you should either do separate queries for the data and the counts, or use a trick. Let's say your table has an id column wich is primary key, you could do:
SELECT count(*) count_all
, sum(if(priv_com = 'Private', 1, 0)) count_private
, sum(if(priv_com = 'Company', 1, 0)) count_company
, classified.*
FROM classified
WHERE classified.classified_id=$id
GROUP BY id -- group by on primary key
WITH ROLLUP
The WITH ROLLUP magic will give you an extra row with the counts for the entire query. The only snag is that you will receive this row as last row of the entire result, so if you want to report the counts before the data, you're going to have to cache the row data in an php array or so and process that later to build up the page.
After your switch variable
$query_priv_comp would be equal to:
SELECT SQL_CACHE * FROM classified WHERE priv_comp='Company'
AND classified.priv_comp='Private'
or
SELECT SQL_CACHE * FROM classified WHERE priv_comp='Private'
AND classified.priv_comp='Company'
Question: What the difference???
You can select all counts with one query:
SELECT priv_comp, COUNT(*) AS record_count FROM classified GROUP BY priv_comp
Then you can query all the records needed for the current tab.
These 2 should be separated clearly.

Categories