Correct SQL Select statement when using BETWEEN - php

I need to do a few things here and I'm confused on how this should work.
Here are the variables I need to work with:
Date Range
Employee ID
Team
and a possible additional search term (acct_number='$_REQUEST[q]') if someone wants to search for a specific account number.
Each variable is populated with a drop down select, the first option being * for all records. The dates are set using a date picker, calendar style, and it's automatically set as date 1=seven days ago and date 2=today.
My query:
SELECT * FROM table
WHERE job_date BETWEEN '$search_date1' AND '$search_date2' AND
employee_id='$searched_employee' AND team='$searched_team' AND
acct_number='$_REQUEST[q]'
ORDER BY employee_id desc
I know the records are there but my search still returns no records. After the date, the AND employee_id='$searched_employee' could be * so it should return all records and the same goes for the team.
Echoing the variables to try make sure something was set gives me this:
No records found for "Employee" for dates between 2011-05-01 and 2011-05-31 and on team "Team".
Can I not request more with AND in the Select statement after I use the BETWEEN?
Thanks in advance!
--Joel

You cannot use '*' wildcard for WHERE clause.
Try using variables for conditions you put in your query, like:
if( is_numeric( $searched_employee ) )
$employee_cond = " AND employee_id=$searched_employee";
else
$employee_cond = "";
and put $employee_cond inside your query instead of AND employee_id='$searched_employee'.
Repeat for every condition you need.

Put parenthesis around the date range condition:
SELECT * FROM table WHERE (job_date BETWEEN '$search_date1' AND '$search_date2') AND employee_id='$searched_employee' AND team='$searched_team' AND acct_number='$_REQUEST[q]' ORDER BY employee_id desc

I don't think its a matter of your BETWEEN statement as it is the amount of criteria you are "AND"ing together. What you are asking for is ALL of the criteria must be true for it to be included in the set...
Ex: Your from/to dates are May 1 to May 31, but the $Searched_Employee you are looking for had no activity within that range, or the employee is not associated with $searched_team, etc with your Acct_Number.
You are explicitly looking for ALL those conditions. You MAY intend to have some "OR" conditions going on... such as
select
Jobs.*,
Employees.LastName,
Employees.FirstName,
Employees.{whatever other columns}
from
Jobs
join Employees on Jobs.EmployeeID = Employees.ID
where
Jobs.job_Date between StartDate and StopDate
AND Jobs.employee_id = SearchedEmployee
AND Jobs.team = SearchedTeam
AND Jobs.Acct_Number = SearchedAccount
The * is only really used such as count() or for fields to be returned from a query, and NOT within where/join conditions (unless its a count() ). So, above has been modified to keep ALL your "AND" clauses, but also show to get specific or all fields from joined table.
The table names querying from are modified as your actual tables were not available. As you can see, I did the Jobs.* to return ALL fields from that table, but explicitly included Employees.{certain individual fields} from that.
Hope this clarification helps you with future querying...

Related

PHP PDO statement with Sum and other column fails

I'm trying to run an SQL query with PDO
This works
$result = $dbo->query("SELECT sum(c) as scfus
FROM tbl
WHERE
YEAR(ondate)=YEAR('".$_POST['startdate']."')
AND MONTH(ondate)=MONTH('".$_POST['startdate']."')
AND DAY(ondate)=$i");
but this does not
$result = $dbo->query("SELECT a,b,sum(c) as scfus
FROM tbl
WHERE
YEAR(ondate)=YEAR('".$_POST['startdate']."')
AND MONTH(ondate)=MONTH('".$_POST['startdate']."')
AND DAY(ondate)=$i");
The only difference is the addition of the a,b column names to the query.
I can run this query (both of them) directly into mysql and get a single record back, as expected, but PDO does not seem to like column names AND sum in the same query?
I can't see a reason, or solution. New to PDO, so was never an issue for me before.
Thanks.
UPDATE - OK, I still think this should work fine, but as a workaround, I've run 2 sql statements, almost exactly the same. One with SELECT SUM(x), one with SELECT a,b, but without the sum. Works fine, but I really should be able to do it in one statement, unless I'm into some PDO limitation I'm not aware of yet.
you might need to GROUP BY c (or whatever column you may want to group domain aggregate function SUM() by) in order to obtain the desired result-set... and maybe take the suggestion above into account.
Try it this way for your query, worked for me for what you want to achieve :
$result = $dbo->query("SELECT a,b,(SELECT sum(c) as whateverFROM tbl),
as scfus
FROM tbl
WHERE
YEAR(ondate)=YEAR('".$_POST['startdate']."')
AND MONTH(ondate)=MONTH('".$_POST['startdate']."')
AND DAY(ondate)=$i");
SUM returns only one line so you'll never get all your results and only the ones of the first matching WHERE criterias (it registers first record found, then only count what it needs).
It will work
Oh, btw, make a timestamp of the date, make a string of the date post in the date sql format and check
WHERE date = $_POST['date']
will work
SELECT a, b , (SELECT SUM(ID)*30 FROM table) FROM table WHERE ID = SOME(SELECT ID FROM tables WHERE users_ID = idYouWant);

In MySQL, what is different between "WHERE IN" and "WHERE"?

Till now I still cannot differentiate between WHERE clause and WHERE IN clause. For example, I have:
Query = mysqli($mysql_connect, "SELECT * From Customer Where CustomerID IN ('CU001', 'CU002', 'CU003')");
Is this same as Query = mysql($mysql_connect, "SELECT * FROM Customer Where CustomerID = 'CU001' AND CustomerID= 'CU002' AND CustomerID='CU003')";?
If it the same, which one is the best practice to follow? Thanks.
The WHERE clause can be combined with AND, OR and NOT operators. The AND and OR operators are used to filter records based on more than one condition. The AND operator displays a record if all the conditions separated by AND is TRUE but should not be used for single column as you have used in 2nd query (it will not find any record).
The In operator finds all records which falls within specified values, like OR condition.

Multiple queries or can be done in one?

I'm not very experienced with more advanced MySQL query stuff.. (mostly basic queries, return and parse response..etc)
However.. I am not clear on the correct approach when I need multiple things (responses) from the database.. Is there a way to get these things from the single query? or do I need to do a new query for each time?
Background:
I use PDO to do a SELECT statement
ie:
$getAllVideos_sql = "SELECT * as FROM $tableName WHERE active IS NOT NULL OR active != 'no' ORDER BY topic, speaker_last, title;";
$getAllVideos_stmt = $conn->prepare($getAllVideos_sql);
$getAllVideos_stmt->execute();
$getAllVideos_stmt->setFetchMode(PDO::FETCH_ASSOC);
$results = $getAllVideos_stmt->fetch(PDO::FETCH_ASSOC);
//parse as I see fit
This gives me my 'chunk of data' that I can pick apart and display as I want.
However.. I want to also be able to give some stats (totals)
For the total (distinct) 'topics'.. as well as total count for the 'titles' (should all be unique by default)
Do I need to do another query, prepare, execute, setFetchMode, fetch all over again?
Is this the proper way to do this? Or is there a way to crib off the initial commands that are already in play?
To be clear, I'm not really looking for a query... I'm looking to understand the proper way one does this.. when they need several pieces of data like I do? multiple queries and executions..etc?
Or maybe it can and -should- be done in one snippet? With an adjustment to the query itself to return sub select/queries info?
this isnt the correct syntax, because it only returns 1 record..(but the total topic count seems to be correct, even though I only get 1 record returned)
SELECT *, count(DISTINCT topic)as totalTopics, count(DISTINCT title)as totalTitles FROM $tableName;
Maybe this the more proper approach? Try to include these totals/details in the main query to pick out?
Hope this makes sense.
Thanks
I don't think you're going to get anything very clean that'll do this, however something like this might work:
SELECT * from $Table t
INNER JOIN (
SELECT COUNT(DISTINCT Topic) as TotalTopics FROM $Table
) s ON 1 = 1
INNER JOIN (
SELECT COUNT(DISTINCT Title) as TotalTitles FROM $Table
) f ON 1 = 1
WHERE ( Active IS NOT NULL ) AND Active != 'no'
Especially with web applications, many people are regularly doing counts or other aggregations somewhere along the way. Sometimes if it is a global context such as all topics for all users, having some stored aggregates helps rather than requerying all record counts every time.
Example. If you have a table with a list of "topics", have a column in there for uniqueTitleCount. Then, based on a trigger, when a new title is added to a topic, the count is automatically updated by adding 1. You can pre-populate this column by doing a correlated update to said "topics" table, then once the trigger is set, you can just have that column.
This also works as I see many times that people want "the most recent". If your system has auto-increment IDs in the tables, similarly, have the most recent ID created for a given topic, or even most recent for a given title/document/thread so you don't have to keep doing something like.
select documentID, other_stuff
from sometable
where documentID in ( select max( documentID )
from sometable
where the title = 'something' )
Use where these make sense then your optimization pull-downs get easier to handle. You could even have a counter per document "title" and even a most recent posting date so they can quickly be sorted based on interest, frequency of activity, whatever.

how to make mysql queries in php run quicker

i am running queries on a table that has thousands of rows:
$sql="select * from call_history where extension_number = '0536*002' and flow = 'in' and DATE(initiated) = '".date("Y-m-d")."' ";
and its taking forever to return results.
The SQL itself is
select *
from call_history
where extension_number = '0536*002'
and flow = 'in'
and DATE(initiated) = 'dateFromYourPHPcode'
is there any way to make it run faster? should i put the where DATE(initiated) = '".date("Y-m-d")."' before the extension_number where clause?
or should i select all rows where DATE(initiated) = '".date("Y-m-d")."' and put that in a while loop then run all my other queries (where extension_number = ...) whthin the while loop?
Here are some suggestions:
1) Replace SELECT * by the only fields you want.
2) Add indexing on the table fields you want as output.
3) Avoid running queries in loops. This causes multiple requests to SQL server.
4) Fetch all the data at once.
5) Apply LIMIT tag as and when required. Don't select all the records.
6) Fire two different queries: one for counting total number of records and other for fetching number of records per page (e.g. 10, 20, 50, etc...)
7) If applicable, create Database Views and get data from them instead of tables.
Thanks
The order of clauses under WHERE is irrelevant to optimization.
Pro-tip, also suggested by somebody else: Never use SELECT * in a query in a program
unless you have a good reason to do so. "I don't feel like writing out the names of the columns I need" isn't a good reason. Always enumerate the columns you need. MySQL and other database systems can often optimize things in surprising ways when the list of data columns you need is available.
Your query contains this selection criterion.
AND DATE(initiated) = 'dateFromYourPHPcode'
Notice that this search criterion takes the form
FUNCTION(column) = value
This form of search defeats the use of any index on that column. Your initiated column has a TIMESTAMP data type. Try this instead:
AND initiated >= 'dateFromYourPHPcode'
AND initiated < 'dateFromYourPHPcode' + INTERVAL 1 DAY
This will find all the initiated items in the particular day. And, because it doesn't use a function on the column value it can use an index range scan to do that, which performs well. It may, or may not, also help without an index. It's worth a try.
I suspect your ideal index for this particular search would created by
ALTER TABLE call_history
ADD INDEX flowExtInit (flow, extension_number, initiated)
You should ask the administrator of the database to add this index if your query needs good performance.
You should add index to your table. This way MySql will fetch faster. I have not tested but command should be like this:
ALTER TABLE `call_history ` ADD INDEX `callhistory` (`extension_number`,`flow`,`extension_number`,`DATE(initiated)`);

Understanding COUNT() as `count`

I'm currently learning how to build a site in PHP MySQL. However, I seem to fail to understand COUNT() as count and wouldn't mind some further explanation.
I get the principles of COUNT, 0 || 1, and how it returns all the values that pertain to that query.
But, don't see how COUNT as count works. Anyhow, this is how the code I'm writing goes - so we have a working example - and where I first became perplexed.
"SELECT COUNT(id) as count, id
FROM user
WHERE email='$email' AND password='".md5$password."'"
That is what is called alias which is sometimes used to show a more appealing column header to users or the calling code
SELECT COUNT(`id`) as `count`....
will print
count
--------
5
The alias standing as the column header instead of any arbitrary string: See the SQLFiddle to see the difference
From the fiddle you can see that the header column looks somehow e.g.
count(*)
--------
5
With Count() you can count the returning rows of a result set. The also the official MySQL documentation about count:
Databases are often used to answer the question, “How often does a certain type of data occur in a table?” For example, you might want to know how many pets you have, or how many pets each owner has, or you might want to perform various kinds of census operations on your animals.
Counting the total number of animals you have is the same question as “How many rows are in the pet table?” because there is one record per pet. COUNT(*) counts the number of rows, so the query to count your animals looks like this:
SELECT COUNT(*) FROM pet;
The part with AS count means that this colum will get a name which you can use e.g. in PHP. See also this explenation on w3schools:
You can give a table or a column another name by using an alias. This can be a good thing to do if you have very long or complex table names or column names.
An alias name could be anything, but usually it is short.
as count is just an alias. You can use as for any field or method selected. it means you change the name of the column being returned in your dataset.
SELECT `field` as another_name
So:
SELECT COUNT(*) as `count`
Just renames the column from COUNT(*) to count making it easier to work with whereever you are maniuplating your result set.
It also makes for easier access within your current query. Many would do the following with large table names:
SELECT * FROM `table_with_ridiculous_name` as twrn WHERE twrn.id = 1
If you ran this sql:
SELECT COUNT(id), id ....
You would get (after doing a *_fetch_assoc) $row['numberofrecordshere'] which would be very hard to echo (or use in a comparison) unless you knew how many records there would be (which would defeat the purpose of this result, anyway)
Returning it as count allows you to get to it in the resulting array by using $row['count']

Categories