MYSQL inventory slots (add item to next slot free) - mysql

$slt = mysql_query("select Slot, ItemId, UserId, max(Slot) Slot
from useritems
group by UserId");
while ($sloot = mysql_fetch_assoc($slt))
{
Echo "<br>Items with biggest slots are: " . $sloot['ItemId'] . " from user " . $sloot['UserId']. "- in slot-". $sloot['Slot'];
}
This is the table
Idi Quantity ItemId UserId Slot ExpirationDate
Outputs the smallest Slots...Why?
1.I want to show me the biggest inventory slot from each user, so when i add a new item to his inventory i can add on next slot..From example user Paul has 5 items that ocupies slots 1,2,3,4,5 and the next item will be on slot 6.
2.When a user moves his items on slots 1,2,4,5,6 the next item added will be on slot 3
I did a lot of search but i can't find out myself:) PS:The game wich im making its just for fun..but maybe someday will be a great game:) (dreams,dreams :)) )
EDIT:
SQLFIDDLE is very good thank you:) it's exactly what i need to learn some SQL
Table useritems
useritems Table IMAGE
items Table
My Echo shows me that:
Id = 1 and it should be 3; user=4(good); slot=4(good)
Id = 1 and it should be 2; user=5(good); slot=2(good)

Maybe something like:
select userid, itemid, max(slot) from useritems where itemid is not null and quantity>0
group by userid, itemid
It'd be easier to help you if you share your table script with some data.
You can use: http://sqlfiddle.com/
EDIT:
What about this? Itemid=0 means the slot is free? So min(slot) will be the first free slot by user.
select userid, min(slot) from useritems where itemid=0 group by userid

I found it!:) i just forgot to select data where UserId=my_id but it shows me the corect output only if the respective user has more than 3 items...
$slt = mysql_query("SELECT * FROM useritems WHERE Slot=(select max(Slot) from useritems) and UserId='$id'");
and $id = $_SESSION['id'];
$slt = mysql_query("
SELECT * FROM `useritems`
WHERE UserId='$id' AND Slot=(select max(Slot)
from useritems where UserId='$id')
");`
EDIT2:I found the best way with all i was searching but i don`t knwo how to use WHERE clause userId='$id'
$slt2 = mysql_query("select l.Slot + 1 as start
from useritems as l
left outer join useritems as r on l.Slot + 1 = r.Slot
where r.Slot is null and l.UserId=4;
") or die(mysql_error()); `
With this query the item should be placed on Slot 2(wich is missing) but it`s dysplays Slot 6 (wich is the highest for the user with UserId=4)
Finally this is the last edit
$slt2 = mysql_query("SELECT Slot + 1 as start
FROM useritems mo
WHERE NOT EXISTS
(
SELECT NULL
FROM useritems mi
WHERE mi.Slot = mo.Slot + 1 AND mi.UserId = '$id'
)ORDER BY Slot LIMIT 1
") or die(mysql_error()); `
This is what i was searching.:X

Related

database query to get lowest price based on last crawel date

I would like to get lowest price of product based on last crawled dates by various resellers. My current function is very basic, it gets me lowest price from table without considering reseller ids and crawled timestamps.
I've rough idea that we can SELECT * FROM "custom_data_table" and process the data using php. Please have a look at attachment for further clarification.
function get_lowest_price($table_id) {
global $wpdb;
$table_prices = $wpdb->get_results(
$wpdb->prepare(
"SELECT price FROM `custom_data_table` WHERE tableid= %d"
,$table_id)
);
if (!empty($table_prices) && $table_prices !== NULL)
return rtrim(min($table_prices)->price, '00');
}
The right query here is:
SELECT price
FROM custom_data_name cdn, (
SELECT MAX(crawled) AS maxCrawled, resellerid
FROM custom_data_name
GROUP BY resellerid
) cdnFiltered
WHERE cdn.crawled = cdnFiltered.maxCrawled AND
cdn.resellerid = cdnFiltered.resellerid AND
tableid = %d;
Try this:
SELECT B.price
FROM (SELECT resellerid, MAX(crawled) max_crawled
FROM custom_data_table
GROUP BY resellerid) A
JOIN custom_data_table B
ON A.resellerid=B.resellerid AND A.max_crawled=B.crawled;
Maybe use ORDER BY crawled and LIMIT 1

Chain of SQL subqueries within large query of JOINS

I am trying to structure a SQL query with complex nested select operation!
My original SQL query successfully JOINS around 30 tables, the data are retrieved as wanted! However every fetched record in the 30 tables
has many records in another table called (Comments)! What I want to do is to atribute every record in the (Comments table) to its record in the other
30 tables by IDs and retrieve them all together in one query. Yet this is not the only challenge, some of the 30 tables have in addition to the records in
(Comments table) more records in another table called (extras), so i am looking for additional subquery within the main subquery within
a LEFT JOIN inside the outter main query.
To make the idea more clear; without subquery the script will be as following:
$query = $mysqli->query("
SELECT
parent1.parent1_id,
parent1.child1_id,
parent1.child2_id,
parent1.child3_id,
parent2.parent2_id,
parent2.child1_id,
parent2.child2_id,
parent2.child3_id,
child1.child1_id,
child1.child1_content,
child2.child2_id,
child2.child2_content,
child3.child3_id,
child3.child3_content
FROM
parent1
LEFT JOIN child1
ON child1.child1_id = parent1.child1_id
LEFT JOIN child2
ON child2.child2_id = parent1.child2_id
LEFT JOIN child3
ON child3.child3_id = parent1.child3_id
LEFT JOIN followers
ON parent1.user_id = followers.followed_id
AND parent1.parent1_timestamp > followers.followed_timestamp
AND parent1.parent1_id NOT IN (SELECT removed.isub_rmv FROM removed)
AND parent1.parent1_hide = false
WHERE
followers.follower_id = {$_SESSION['info']}
{$portname_clause}
ORDER BY
parent1.parent1_timestamp DESC
LIMIT
{$postnumbers}
OFFSET
{$offset}
")
// Now fetching and looping through the retrieved data
while($row = $query->fetch_assoc()){
echo $row['child1_content'];
$subquery1 = $mysqli->query("SELECT extras.child1_id,
extras.extrasContent FROM extras WHERE extras.child1_id =
{$row['child1_id']}");
while($row1 = $subquery1->fetch_assoc()){
echo $row1['extrasContent'];
}
echo $row['child2_content'];
$subquery2 = $mysqli->query("SELECT extras.child2_id,
extras.extrasContent FROM extras WHERE extras.child2_id =
{$row['child2_id']}");
while($row2 = $subquery2->fetch_assoc()){
echo $row2['extrasContent'];
}
echo $row['child3_content'];
$subquery3 = $mysqli->query("SELECT extras.child3_id,
extras.extrasContent FROM extras WHERE extras.child3_id =
{$row['child3_id']}");
while($row3 = $subquery3->fetch_assoc()){
echo $row3['extrasContent'];
// Here i need to run additional query inside the subquery 3 to retrieve the (Comments table) data beside (extras table)
$subquery4 = $mysqli->query("SELECT comments.comment_id, comments.comment FROM comments WHERE comments.child3_id = {$row['child3_id']} OR comments.child3_id = {$row3['child3_id']}");
while($row4 = $subquery4->fetch_assoc()){
echo $row4['comment'];
}
}
} // No sane person would make such code
Because the code above would be totally rediclious i searched for a better way to carry it out, and thats where i came across the subquery
concept, but i do not know anything about subqueries, and shortly after i studied it i came up with this messy code, check it below!
I am not posting the origianl code here because it is too long, i am including a virtual example of the tables i want to apply the
query on in order to demonstrate the process.
SELECT
parent1.parent1_id,
parent1.child1_id,
parent1.child2_id,
parent1.child3_id,
parent2.parent2_id,
parent2.child1_id,
parent2.child2_id,
parent2.child3_id
FROM
parent1
LEFT JOIN
( SELECT
child1.child1_id,
child1.child1_content
FROM
child1
WHERE
child1.child1_id = parent1.child1_id ) child1
( SELECT extras.extrasID, extras.extrasContent
FROM
extras
WHERE
extras.child1_id = child1.child1_id )
ON parent1.child1_id = child1.child1_id
LEFT JOIN child2
( SELECT
child2.child2_id,
child2.child2_content
FROM
child2
WHERE
child2.child2_id = parent1.child2_id )
( SELECT
extras.extrasID,
extras.extrasContent
FROM
extras
WHERE
extras.child2_id = child2.child2_id )
ON parent1.child2_id = child2.child2_id
LEFT JOIN child3
( SELECT
child3.child3_id,
child3.child3_content
FROM
child3
WHERE
child3.child3_id = parent1.child3_id )
( SELECT
extras.extrasID,
extras.extrasContent
FROM
( SELECT
comments.comment_id,
comments.comment
FROM
comments
WHERE
comments.child3_id = extras.child3_id ) extras
JOIN child3
ON extras.child3_id = child3.child3_id )
ON parent1.child3_id = child3.child3_id
LEFT JOIN followers
ON parent1.user_id = followers.followed_id
AND parent1.parent1_timestamp > followers.follower_timestamp
AND parent1.parent1_id NOT IN (SELECT removed.isub_rmv FROM removed)
AND parent1.parent1_hide = false
WHERE
followers.follower_id = {$_SESSION['info']}
{$portname_clause}
ORDER BY
parent1.parent1_timestamp DESC
LIMIT
{$postnumbers}
OFFSET
{$offset} // <-- Sorry for the bad code formatting!
I am using MySql 5.6.37
I did not get the hang of the subquery concept yet, frankly i got lost and confused as i was studying it and for another reason too mentioned in the note below.
Note: I apologize in advance that i might not be on instant reply because where i live there is no electrecity or ADSL or phones and my
USB modem hardly gets signal, i have only two hours of averege three hours a day of electericity generated by a desil generator. i recharge
my laptop and check internet and the remaining one-two hours are for other life stuff.
I know the joke is on me as i am developing a web project without electricity or permanent internet. BUT LIFE DOES NOT GIVE EVERYTHING! lol.
This is how i solved the problem!
SELECT
parent1.parent1_id,
parent1.child1_id,
child1.child1_id,
child1.child1_content,
comments.comment_id,
comments.comment,
comments.child1_id
FROM parent1 LEFT JOIN
(
SELECT comments.comment_id, comments.comment, comments.child1_id
FROM
(
SELECT comments.comment_id,comments. comment, comments.child1_id
FROM comments
) comments JOIN child1
ON comments.child1_id = child1.child1_id
) comments
ON child1.child1_id = comments.
It needs some aliases and then it's good to go.

Data is being shown multiple times

I am having only one record under the cust_vend_relation
But its being displayed two times.
QUERY
select cvr.customer_id,
cvr.address_label,
cvr.vendor_name,
cvr.vendor_id,
vhd.locality,
vhd.area,
vhd.address,
vhd.city,
vhd.state
from cust_vend_relation cvr, vendor_home_delivery vhd
where cvr.vendor_id = vhd.vendor_id
and cvr.address_label = 'Office'
and cvr.customer_id = 3;
This is my sqlfiddle
I need to show only the records present under the table cust_vend_relation that matches with the records present under the vendor_home_delivery.
could anybody please help me .
Add Group By customer_id
select
cvr.customer_id,
cvr.address_label,
cvr.vendor_name,
cvr.vendor_id,
vhd.locality,
vhd.area,
vhd.address,
vhd.city,
vhd.state
from cust_vend_relation cvr, vendor_home_delivery vhd
where cvr.vendor_id = vhd.vendor_id and cvr.address_label = 'Office' and cvr.customer_id = 3 group by customer_id;

mysql select count(column) where sum(column) > value

I'm trying to query $wpdb to get back an int value of the number of users in a custom table who have recorded a number of hours volunteer work above a set target - these hours need to have been moderated ( value set to = 1 ) - I have this so far:
EDIT - updated to use consistent {} around php variables in query --
$target = get_post_meta($post->ID, 'target', true) ? (int)get_post_meta($post->ID, 'target', true) : 100;
$awards = $wpdb->get_var("
SELECT user_id
FROM {$this->options['rewards_logging']}
WHERE moderated = 1 AND reward_id = {$post->ID}
GROUP BY user_id
HAVING sum(hours) > {$target}
");
Which returns the correct value of '0' if none of the hours are approved ( moderated = 0 ), however as soon as one of those users hours are approved, this query returns the count of all the users who have logged more than the target hours ( whether they have been approved or not ).
Any pointers!
Cheers
Ray
Seems I was trying to get back a single variable using $wpdb->get_var, when I really needed the whole result set:
$awards = $wpdb->get_results("
SELECT user_id
FROM {$this->options['rewards_logging']}
WHERE moderated = 1 AND reward_id = {$post->ID}
GROUP BY user_id
HAVING sum(hours) > {$target}
");
Then I can check over the data and display a result - etc...:
if ( count($awards) > 0 ) {
#var_dump($awards);
echo '<span class="awards-notice">'.count($awards).'</span>';
} else {
echo '-';
}

Simple mySQL subqueries

I have a simple problem, but I am new to SQL so please forgive my ignorance.
I have a accounting report that figures out balances oweing and adds up the balances to report to me what the total outstanding are within a specific period. The issue is for every JOB there are many invoices that provide a running total/balance, because of this when my current query adds up the balances it shows me outstanding amounts that are sky high, we have found that the current code is adding the balances of all the invoices.
Example-
If JOB ID 001 has four invoices-
I-001 balance 200,
I-002 balance 100,
I-003 balance 50,
I-004 balance 0.
It will show me that there is $350 outstanding when in fact it is zero.
The solution that I can think of(which I am not sure how to code) are to group the results by job ID and use the MAX feature to select only the higest ID for every JOBID
The problem I am having is that the balances are not saved to the table but recalculated every time they are needed. What can you suggest to show me only the balance from the highest Invoice ID for a particular JOBID
My invoice table has the following columns:
1 ID int(11)
2 ParentID int(11)
3 JOBID varchar(100)
4 DATE date
5 LENSES decimal(10,2)
6 FRAMES decimal(10,2)
7 TAXABLEGOODS decimal(10,2)
8 DISCOUNT decimal(10,2)
9 PREVIOUSBALANCE decimal(10,2)
10 PAYMENT decimal(10,2)
11 PAYMENTTYPE varchar(200)
12 NOTES varchar(255)
13 PMA decimal(10,2)
The current code looks like this:
$pieces = explode("-", $_REQUEST["STARTDATE"]);
$startDate=$pieces[2] . "-" . $pieces[1] . "-" . $pieces[0];
if($_REQUEST["ENDDATE"]==""){
$endDate=0;
}else{
$pieces = explode("-", $_REQUEST["ENDDATE"]);
$endDate = $pieces[2] . "-" . $pieces[1] . "-" . $pieces[0];
}
$result = mysql_query("SELECT * FROM INVOICES WHERE DATE BETWEEN '" . $startDate . "' AND '" . $endDate . "'");
$totalCount = 0;
$total = 0;
$allPayments= 0;
$pmtTypes = Array();
$totalHST = 0;
$outstanding=0;
$payments=0;
while($theRow=mysql_fetch_array($result)){
$allPayments += $theRow["PAYMENT"];
if($theRow["PAYMENTTYPE"] == "") $theRow["PAYMENTTYPE"] = "BLANK";
if(isset($pmtTypes[$theRow["PAYMENTTYPE"]])){
$pmtTypes[$theRow["PAYMENTTYPE"]] += $theRow["PAYMENT"];;
}else{
$pmtTypes[$theRow["PAYMENTTYPE"]] = $theRow["PAYMENT"];;
}
if($theRow["PREVIOUSBALANCE"] != 0) continue;
$subTotal = ( ( $theRow["LENSES"] + $theRow["FRAMES"] + $theRow["TAXABLEGOODS"] ) - $theRow["DISCOUNT"]);
$HST = ( $theRow["TAXABLEGOODS"] * 0.13 );
$totalHST+= $HST;
$total += ( $subTotal + $HST );
$payments+=$theRow["PAYMENT"];
}
$outstanding=$total-$payments;
Anyone have anything to contribute?
I would appreciate any help.
show me only the balance from the highest Invoice ID for a particular JOBID
For a single job ID:
SELECT lenses+frames+taxablegoods-discount+previousbalance AS balance
FROM invoices WHERE jobid=?
ORDER BY id DESC LIMIT 1
group the results by job ID and use the MAX feature to select only the higest ID for every JOBID
If you want to query the latest invoice for many jobs at once, you are talking about a per-group-maximum selection. SQL doesn't make this as easy to do as you'd hope. There are various approaches, including subqueries, but on MySQL I typically favour the null-self-join:
SELECT i0.jobid, i0.lenses+...etc... AS balance
FROM invoices AS i0 LEFT JOIN invoices AS i1 ON i1.jobib=i0.jobid AND i1.id>i0.id
WHERE i1.id IS NULL
That is: “give me rows where there is no row with the same job ID but a higher invoice ID”.
If doing this between two dates, you'd need to apply the condition to both sides of the join:
SELECT i0.jobid, i0.lenses+...etc... AS balance
FROM invoices AS i0 LEFT JOIN invoices AS i1 ON
i1.jobib=i0.jobid AND i1.id>i0.id AND
i1.date BETWEEN ? AND ?
WHERE
i0.date BETWEEN ? AND ?
i1.id IS NULL
Incidentally you have an SQL-injection vulnerability from putting strings into your query. Use mysql_real_escape_string() or, better, parameterised queries to avoid these problems.
The subquery would look something like this:
SELECT * FROM INVOICES I1
WHERE DATE BETWEEN ? AND ?
AND ID = (SELECT MAX(ID) FROM INVOICES I2
WHERE DATE BETWEEN ? AND ?
AND I2.JOBID = I1.JOBID)
You should look into using parameterised queries, instead of concatenating the string with user input. At a bare minimum use mysql_real_escape_string - see here: http://www.php.net/manual/en/function.mysql-real-escape-string.php