I got this answer from somebody on another Q before, but I would like to get an explanation of this, so that I fully understand the problem.
I have a table, with a column which contains a value of either "private" or "company".
Thing is, I want to check how many "private" and "company" values are in my records, so that I can display them with the search results later on.
So if there are 4 company ads, and 1 private ad, this is the results:
Company = 4
Private = 1
All ads = 5
And here is the code I got from someone about how to do this, in other words, this is what I would like explained:
SELECT
IFNULL( field , 'All ads' ) AS 'Type',
COUNT( * )
FROM
`table`
GROUP BY
field
WITH ROLLUP
Thanks
I assume that the part you don't understand is the ROLLUP clause, which is not often used.
The manual describes it well, but the basic idea is that each group is aggregated, and then you get one extra group at the end which aggregates the rows from all groups, and where Field is set to NULL.
The IFNULL expression changes the NULL to a readable string instead. You could use COALESCE instead of IFNULL to get the same effect.
Select the Type field, and if the value is null, use All Ads as the default value.
Select them from the table, and group them by field.
As far as I can tell, this will count each the number of entries of each 'Type', and all the entries that have a null value will simply go under the 'All Ads' count.
Just BTW, if you look at the IFNULL() function, it is pretty easy to figure out. It clearly states IF NULL, so it is checking if something is null. Then you pass it a field name and a static value. Kind of makes sense that it is checking if that field value is false. And the only other thing there is the value, so we can come to the conclusion that it will use the static value, if the field value is null.
Selects all adverts from the table "table", it groups them by field, this means that all the ads that are "public" are placed into a group "public" with an associated number. So if you have 10 public adverts they're all grouped into "public adverts" with the value 10.
Does this make sense?
Related
Is there a possible way to get the value from a custom parameter inside a column.
As you can see in the picture below. I have a column name Parameters, and has a value of custom parameters.
1.) Is there any way that I can only get the price and its corresponding value inside that column name?
2.) Is there any possible way to decipher the format?
3.) Can you give me a idea how to parse it accordingly?
Click this to see the picture
Im just curious guys. Thanks in advance for those who will helping me out.
Assuming the string pattern always starts like 'price<=>' (i.e. 9 characters in start). You can use below query to check the price and compare it.
The inner query uses substring to find the price value from matching rows. Outer query can be used to perform comparison as you want.
SELECT
*
FROM
(SELECT
SUBSTRING(parameters, 9) AS price
FROM
your_table
WHERE
parameters REGEXP 'price<=>[0-9]') t
WHERE
price > 1000;
I have a large database and even with indexes it's slowing down a lot when I use SELECT DISTINCT. I thought I'd change it to use an array instead but somehow it's not working. What am I doing wrong?
The original code is:
$product_countries = $this->query("SELECT DISTINCT country FROM db_products");
$listing_countries = array();
while ($listing_details = $this->fetch_array($product_countries)){
if (!empty($listing_details['country'])){
$listing_countries[] = $listing_details['country'];
}
}
Now, I tried changing it to:
// $product_countries = $this->query("SELECT DISTINCT country FROM db_products");
$product_countries = array("2084", "1993");
And the while part to:
while ($listing_details = $product_countries){
But that's not working. What am I doing wrong here? I'm pretty sure it's somewhere in that while line and the fact that the before it used a mySQL resource and then afterwards I changed it to an array, but I can't figure it out :(
Given:
$product_countries = array("2084", "1993");
There's no need for a while loop. Just get the contents of that array assigned to another array. Like this:
$product_countries = array("2084", "1993");
$listing_details = $product_countries;
And be done with it. (You already know that the values in the $product_countries array are already defined, and aren't going to evaluate to FALSE, so there's no need for any conditional test.
With the while loop as you show, how will that ever exit? Looks like a classic infinite loop to me.
If that's not the question you are asking...
As far as the MySQL query goes, the only appropriate index for the query would be a BTREE index (not a HASH index) with a leading column of country. Ideally (for this query) on just that single column:
... ON db_products(country)
The query should be equivalent to a GROUP BY query:
SELECT country FROM db_products GROUP BY country
I recommend you run an EXPLAIN on the query to verify that it's using an index and not doing a "Using filesort" operation. (This assumes that db_products is a table, and not some harebrained view definition.)
I'm not understanding why the conditional test on the return of the empty function is needed. If fetch_array returned a row, then variable is going to be defined, so that test really only checking if the value returned from the database evaluates to FALSE. If I wanted to exclude values of country that evaluate to FALSE, I would tend to include the appropriate predicate in the query definition.
First, this query:
SELECT DISTINCT country
FROM db_products
should be able to make good use of an index on db_products(country).
Second, you should have a separate table of countries, with db_products containing a countryId, referring to the other table. If you had that, then displaying the list of countries would be a no-brainer.
AS I stated in the comments, the better way to do this is have a list of countries in a separate table, and reference them in your product table.
This is called normalization, generally you should think of it like this. A product is a thing with certain attributes of which country is only one, it might have a price, or a SKU number for example..
Countries too are a thing, they may have abbreviations, shipping codes, laws that deal with this or that, many things. They are not as simple as say a SKU number or a price. But, could contain other useful data unrelated to a specific product, don't they deserve a table all their own?
It's hard to say the structure of this table or the relationship between a product and a country without knowing more. But, you may be able to eliminate a lot of redundant data. Ask yourself these two things:
Can a product have more then one country?
Can a country supply more then one product?
Those will tell you the relationship you need.
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']
I have one table called cf_posts
ID pk
user INT
subject VARCHAR
body TEXT
datetime TIMESTAMP
parent INT
category INT
mod INT
When a post is submitted to the forum the default parent is 0, when a post is submitted as a reply, then its parent is the ID of the original post.
How can I make it so that the default view of the forum main page is ordered that the most recently updated post (including the latest replies) would be at the "top" of the pile, and working down in date order? What would be the PHP/MySQL query?
The only workarounds I have seen for this are separate topics and reply tables, but I'd like to stay away from this approach if possible.
One workaround that I tried and failed was GROUP BY parent.
But this grouped all topics that had no replies together as one.
Another idea that I have yet to try is to make the parent id of the original post match the post ID, and not include matching ID and parent IDs in the output.
I look forward to hearing your thoughts.
SELECT mainPost.subject, lastPost.datetime
FROM cf_posts cfp,
(
SELECT *
FROM cf_posts subPost
WHERE subPost.parent = mainPost
ORDER BY subPost.datetime DESC
LIMIT 1
)lastPost
WHERE mainPost.parent IS NULL
This is done briefly, so there may be some syntax issues but I think this should help.
You can do the following: query each separate thing that you need, so maybe a query for each topic, Then you can use UNION to bunch all of them together to get one list. Now the trick to preserve an order is as followed. For each separate query append a column to the returned result called sort and set each instance of that to a higher int value, then you can guarantee that the final result is properly sorted. Go review UNION for select statements to get a better understanding of what I'm talking about.
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...