Query to retrieve values that don't exist between tables - php

I need to retrieve values that doesn't exist in another table. I'm working with Shares and Share_types tables.
Currently, I have this working with PHP but I'm always looping all over the 2,500~ rows of Share_types and I think it is possible to solve the amount of rows with a query.
The user currently goes through this process:
Select the type of share - Anual share
Select the year that will be extracted - 2016
Code will generate all shares until the year of 2016 that weren't yet generated. This means, that the years behind of 2016 will also be generate if they don't exist.
That said, my PHP code is like the following:
// Retrieves always the 2,500~ rows
$listOfShareTypes = "SELECT user_id, date_start FROM share_types WHERE type = 'Anual share'";
foreach($listOfShareTypes as $type)
{
// Now is where I validate if the share already exists
$hasShare = "SELECT COUNT(*) FROM shares WHERE the_year = $yearSelectedByUser, user_id = $type->user_id, share_type_id = $type->id";
if($hasShare == TRUE)
continue;
else
// Create the share..
}
So usually, to retrieve via query the results that doesn't exist in another table I would do two select in a query, but after a few searches it points to the use of LEFT JOIN. However I have no clue how to accomplish this since I need to match several fields (user_id, share_type_id, year, etc.)
Looking at this example I created on SQLFiddle, the result should be:
(5, 3, 'Anual', '2015-06-28')
And with this result and since the user selected the year of 2016 I should loop (in PHP) from 2015 until 2016.

You were using the wrong column in the join condition. The tables should be joined on user_id.
SQL Fiddle
SELECT stype.id, stype.user_id, stype.type, stype.date_start
FROM share_types AS stype
LEFT JOIN shares AS share ON share.user_id = stype.user_id
WHERE share.share_type_id IS NULL

try this query
SELECT user_id, date_start FROM share_types st,shares sh on sh.share_type_id=st.user_id WHERE type = 'Anual share' and sh.user_id=st.id and sh.the_year=$yearSelectedByUser and Having COUNT(sh.user_id) < 1;

Related

mysqli Table Joining

I’m using Ajax to retrieve information from my database. I have no trouble sending to server PHP and getting information back using simple SQL queries. I came across a section that I needed to pull from 2 tables (Same Database) Both in common are column PO. Attached is a picture of an example.
I have been trying to pull everything from one table that meets my condition like Month of, year of and Store. I have been able to JOIN them but not successfully. Closest I ever got is it checks both tables and only returns the data that have matching PO and not the rest of Table 1.
I like for it to retrieve all rows in table one that meet the conditions and if there is a matching PO in table2 join it else continue to retrieve from table1.
Please any help would be grateful
I figured it out. Thank you
$sql = "SELECT * FROM weekly_report LEFT JOIN tracker ON weekly_report.PO = tracker.POt WHERE MONTH(STR_TO_DATE(`Need By Date (Date)`, '%m-%d-%Y')) = '$month' AND YEAR(STR_TO_DATE(`Need By Date (Date)`, '%m-%d-%Y')) = '$year' AND weekly_report.`Ship To Location (Location ID)` LIKE '%$store%' GROUP BY (weekly_report.PO)";

Select Data Based on Column Less Than Current Date and Empty Columns

For example, i have two tables like this
Table User:
Table Payment:
I want to join two table above, but i want to get the result as quantity,
How many of blanks price columns based from previous of current date.
So if current date is 2015-04-10, the result will be look like this:
I don't have any clue how to do that using some syntax query combination in SQL or in PHP to display the result
In SQL, you could do something like this:
SELECT user_name, COUNT(name) AS result
FROM user
JOIN payment ON users.id = payment.id_user
WHERE (price IS NULL OR ltrim(price) = '')
AND payments.last_pay < '2015-04-10'
GROUP BY payment.id_user
You can see the result of this query in the SQL Fiddle.

SQL Join can't figure it out

I have a table called website that contains some data about websites. The columns of this table are: id, website, quick_url, user_id, status, etc.
Each website that is in the table was added by a user, which is is saved in the user_id column.
I have another table called blocks that has only 3 columns: id, user_id, website_id.
I want to get all the websites from the website table, that were not added by a given user_id, but also, only the websites that were not blocked by the given user_id. So, websites that were not added by a given user or blocked by him.
Here is what I've tried:
SELECT * FROM website LEFT OUTER JOIN blocks ON tbl_website.userid = blocks.user_id WHERE website.user_id = blocks.user_id AND blocks.user_id = NULL AND website,user_id != '177' LIMIT 500;
It doesn't give me the wanted results ...
First, I've tried to do it like this:
SELECT * FROM tbl_website WHERE id<>(SELECT website_id from tbl_website_blocks WHERE user_id = '177')
which makes much more sense for me than my previous query, but I get this error: Subquery returns more than 1 row
I guess you can't have a "loop in loop" in an SQL query.
I'm aware that I could do two queries, and filter the results, but I would like to do it as much as possible from the SQL language, so that I don't "overload" the server.
Any suggestions would be appreciated.
In your second query rewrite the condition on
WHERE id not in (SELECT website_id from.....)
with <> you can compare it with just one value but your select returns list of values, so you can use not in to get results that are different then the selected list of IDs
Instead of '<>', try 'Not In'
SELECT * FROM tbl_website
WHERE id Not In (SELECT website_id from tbl_website_blocks WHERE user_id = '177')
I should also add this query is not a Join.

Running a query on query result? (PHP + SQL)

I currently have a table with 1,100,000 rows which contains user's data.
Its format is sort of like this:
User_Id Date Action
I was wondering, instead of searching each time on the whole table for the actions that were made by a specific user on a specific date by doing the following:
SELECT Action FROM USERS_TABLE WHERE Date=08092014 AND User_Id=5
SELECT Action FROM USERS_TABLE WHERE Date=09092014 AND User_Id=5
SELECT Date FROM USERS_TABLE WHERE Action="Shopping" AND User_Id=5
SELECT Date FROM USERS_TABLE WHERE Action="Eating" AND User_Id=5
etc.
Maybe I could do something like that:
SELECT * FROM USERS_TABLE WHERE User_Id=5
And on top of this query's results I could run the above queries, which I think will result a faster execution time (correct me if I'm wrong)
Do you guys know how to do that?
You could combine all of those queries into one query using an or.
SELECT *
FROM USERS_TABLE
WHERE (Date = 09092014 OR Date = 08092014)
AND (Action="Shopping" OR Action="Eating")
AND User_Id = 5
I assume you have a table with unique users ids. if you don't, you might consider it? How can a profile be managed if there is no single entry for a single user? anyway that's not my business, but let's just assume you have such a table, with a unique field with the User_Id
it's named USERS here
SELECT Action,Date
FROM USERS
LEFT JOIN USERS_TABLE AS Actions
ON (Actions.User_Id=USERS.User_Id AND Date IN (08092014,09092014))
LEFT JOIN USERS_TABLE AS Dates
ON (Dates.User_Id=USERS.User_Id AND Action IN ("Shopping","Eating"))
WHERE USERS.User_Id=5
be sure to index User_Id, Date And Action since we are searching on them.
I would do a crosstab query, after I indexed the User_Id column -
SELECT `Date`,
SUM(IF(`Action` = 'Eating', 1, 0)) AS `Eating`,
SUM(IF(`Action` = 'Shopping', 1, 0)) AS `Shopping`
FROM `USERS_TABLE`
WHERE `User_Id` = 5
GROUP BY `Date`
You'll get a result like this -
+-------------+---------------+----------+
Date Eating Shopping
+-------------+---------------+----------+
2002-03-01 59 72
2002-03-02 28 0
2002-03-03 22 17
2002-03-04 36 13
2002-03-06 12 0
+-------------+---------------+----------+
For expediency I might store this data in a temp table (with a user id column). This can be modified to accept date ranges and other limitations. That gives me some additional flexibility down the line when I need to aggregate date from multiple users.
I think what you mean is answered by this:
select action, actiondate
from
(select *
from USERS_TABLE
where user_id = 5) as filter
Fiddle here.
The derived table basically acts as the filter you describe.
Whether it would be any faster is hard to predict - I'd run it on your production system, and see what the query plan says.

How to find the next available integer in MySQL table using PHP

I know auto_increment is the way to go but I can not use auto_increment feature since the column in my table might repeat, its not unique. When I insert a new row to a table I need a way to find the next available spot to insert it.
For example table structure:
Primary Key = (ID, UserID)
ID UserID
3 6
3 1
1 3
Now when i do insert query i want to isert it at ID = 2 and not 4. With auto_increment it gives me 4
Is there a solution without using the loop in PHP? So far what i have is I fetch all rows into array and then find the next available digit in ID. Is it possible to do this without fetching all rows in PHP and just doing it on MySQL query ?
SELECT t1.id+1 AS MISSING_ID
FROM the_table AS t1
LEFT JOIN the_table AS t2 ON t1.id+1 = t2.id
WHERE t2.id IS NULL
ORDER BY t1.id LIMIT 1;
I made a fiddle: http://sqlfiddle.com/#!2/4d14d/2
No, it is not possible without processing the data. The preferred method to correct this issue is to adjust your table structure to support a unique, auto-incrementable field. Failing that, you will have to process the data (either in PHP or via an SQL statement) to find an open slot.
This should do the trick:
SELECT
min_table.ID+1 AS start,
MIN(max_table.ID) - 1 AS end
FROM
your_table AS min_table,
your_table AS max_table
WHERE
min_table.ID < max_table.ID
GROUP BY
min_table.ID
HAVING
start < MIN(max_table.ID)
The left hand column will return the first available spot in the sequence gap, and the second is the highest number in that particular gap.
Source: http://www.codediesel.com/mysql/sequence-gaps-in-mysql/
My workaround for not loaded project:
Suppose, you have questionset with question_id 's which belong to certain topic_id.
Suppose, user navigates and clicks "<Prev" "Next>" buttons to navigate questions.
You have only current id. Catching the direction of navigation, topic_id, question_id you can do a loop
do {
// query base, doing question_id++ or question_id-- depending on needed direction until you find next id within topic_id
} while( id!=null ) `
using incrementation or decrementation depending on direction of your move

Categories