I have a table of customers with a 1 recorded against their customerid on different dates.
I would like to find the sum of the 1's recorded in descending order. I'm using MySQL and php
Thanks
My guess is that you want the sum of records marked with 1 per customer and sort that result in descending order? If so, the following should do the trick :
select cust.id, sum(cone.one) as number_ones
from customers as cust
inner join customer_ones as cone on cone.id=cust.id
group by cust.id
order by number_ones desc
This is assuming that 'one' is the column containing ones (and only contains 0 or 1 - otherwise you will have to add WHERE cone.one = 1), customers is your customer table and customer_ones is the table containing your customer data.
As i get you right, this is simple sql request what u need:
SELECT COUNT(id) as total from customers
Just make in php:
$sql="SELECT COUNT(id) from customers";
$query=mysql_query($sql) or die(mysql_error());
$res=mysql_fetch_assoc($query);
$summ=$res['total']; //<- Your summ (i.e. quantity of rows in table)
Btw, you can use mysql_num_rows instead.
Or explain please more accurately what output you need. To make sorting by date or any other dependency you will need to make other request using WHERE clause and date comparison.
Related
Lets start by saying that I cant use INDEXING as I need the INSERT, DELETE and UPDATE for this table to be super fast, which they are.
I have a page that displays a summary of order units collected in a database table. To populate the table an order number is created and then individual units associated with that order are scanned into the table to recored which units are associated with each order.
For the purposes of this example the table has the following columns.
id, UID, order, originator, receiver, datetime
The individual unit quantities can be in the 1000's per order and the entire table is growing to hundreds of thousands of units.
The summary page displays the number of units per order and the first and last unit number for each order. I limit the number of orders to be displayed to the last 30 order numbers.
For example:
Order 10 has 200 units. first UID 1510 last UID 1756
Order 11 has 300 units. first UID 1922 last UID 2831
..........
..........
Currently the response time for the query is about 3 seconds as the code performs the following:
Look up the last 30 orders by by id and sort by order number
While looking at each order number in the array
-- Count the number of database rows that have that order number
-- Select the first UID from all the rows as first
-- Select the last UID from all the rows as last
Display the result
I've determined the majority of the time is taken by the Count of the number of units in each order ~1.8 seconds and then determining the first and last numbers in each order ~1 second.
I am really interested in if there is a way to speed up these queries without INDEXING. Here is the code with the queries.
First request selects the last 30 orders processed selected by id and grouped by order number. This gives the last 30 unique order numbers.
$result = mysqli_query($con, "SELECT order, ANY_VALUE(receiver) AS receiver, ANY_VALUE(originator) AS originator, ANY_VALUE(id) AS id
FROM scandb
GROUP BY order
ORDER BY id
DESC LIMIT 30");
While fetching the last 30 order numbers count the number of units and the first and last UID for each order.
while($row=mysqli_fetch_array($result)){
$count = mysqli_fetch_array(mysqli_query($con, "SELECT order, COUNT(*) as count FROM scandb WHERE order ='".$row['order']."' "));
$firstLast = mysqli_fetch_array(mysqli_query($con, "SELECT (SELECT UID FROM scandb WHERE orderNumber ='".$row['order']."' ORDER BY UID LIMIT 1) as 'first', (SELECT UID FROM barcode WHERE order ='".$row['order']."' ORDER BY UID DESC LIMIT 1) as 'last'"));
echo "<td align= center>".$count['count']."</td>";
echo "<td align= center>".$firstLast['first']."</td>";
echo "<td align= center>".$firstLast['last']."</td>";
}
With 100K lines in the database this whole query is taking about 3 seconds. The majority of the time is in the $count and $firstlast queries. I'd like to know if there is a more efficient way to get this same data in a faster time without Indexing the table. Any special tricks that anyone has would be greatly appreciated.
Design your database with caution
This first tip may seems obvious, but the fact is that most database problems come from badly-designed table structure.
For example, I have seen people storing information such as client info and payment info in the same database column. For both the database system and developers who will have to work on it, this is not a good thing.
When creating a database, always put information on various tables, use clear naming standards and make use of primary keys.
Know what you should optimize
If you want to optimize a specific query, it is extremely useful to be able to get an in-depth look at the result of a query. Using the EXPLAIN statement, you will get lots of useful info on the result produced by a specific query, as shown in the example below:
EXPLAIN SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column;
Don’t select what you don’t need
A very common way to get the desired data is to use the * symbol, which will get all fields from the desired table:
SELECT * FROM wp_posts;
Instead, you should definitely select only the desired fields as shown in the example below. On a very small site with, let’s say, one visitor per minute, that wouldn’t make a difference. But on a site such as Cats Who Code, it saves a lot of work for the database.
SELECT title, excerpt, author FROM wp_posts;
Avoid queries in loops
When using SQL along with a programming language such as PHP, it can be tempting to use SQL queries inside a loop. But doing so is like hammering your database with queries.
This example illustrates the whole “queries in loops” problem:
foreach ($display_order as $id => $ordinal) {
$sql = "UPDATE categories SET display_order = $ordinal WHERE id = $id";
mysql_query($sql);
}
Here is what you should do instead:
UPDATE categories
SET display_order = CASE id
WHEN 1 THEN 3
WHEN 2 THEN 4
WHEN 3 THEN 5
END
WHERE id IN (1,2,3)
Use join instead of subqueries
As a programmer, subqueries are something that you can be tempted to use and abuse. Subqueries, as show below, can be very useful:
SELECT a.id,
(SELECT MAX(created)
FROM posts
WHERE author_id = a.id)
AS latest_post FROM authors a
Although subqueries are useful, they often can be replaced by a join, which is definitely faster to execute.
SELECT a.id, MAX(p.created) AS latest_post
FROM authors a
INNER JOIN posts p
ON (a.id = p.author_id)
GROUP BY a.id
Source: http://20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck/
I am trying to retrieve random rows from mysql using RAND() function. But in result rows are repeating more than once. Is there any way to return random rows in such a way that a row is returned only once?
My query is: SELECT h.recid recid, h.name name, h.subtitle subtitle, h.pricingfrom pricingfrom FROM holydays h ORDER BY RAND()
I found this solution but I didnt understand how it works as I don't have any limits...
Any answer will be appreciated.!
The ORDER BY clause of a query has nothing to with the result set, except maybe if LIMIT is being used, which it is not here. It sounds to me like your table has some duplicate records. If you want a random ordering with no duplicates, then select with DISTINCT:
SELECT DISTINCT
recid,
name,
subtitle,
pricingfrom
FROM holydays
ORDER BY RAND();
it's work by order by taking random columns
ex, there is id, name, emai then some time it order id,name,email or some time name,id,emai etc. etc. and it some time order in asc and some time in desc. That's logic.
Im currently working on a project that requires MySql database and im having a hard time constructing the query that i want get.
i want to get the previous 10 rows from the specific WHERE condition on my mysql query.
for example
My where is date='December';
i want the last 10 months to as a result.
Feb,march,april,may,june,july,aug,sept,oct,nov like that.
Another example is.
if i have a 17 strings stored in my database. and in my where clause i specify that WHERE strings='eyt' limit 3
Test
one
twi
thre
for
payb
six
seven
eyt
nayn
ten
eleven
twelve
tertin
fortin
fiftin
sixtin
the result must be
payb
six
seven
Thanks in advance for your suggestions or answers
If you are using PDO this is the right syntax:
$objStmt = $objDatabase->prepare('SELECT * FROM calendar ORDER BY id DESC LIMIT 10');
You can change ASC to DESC in order to get either the first or the last 10.
Here's a solution:
select t.*
from mytable t
inner join (select id from mytable where strings = 'eyt' order by id limit 1) x
on t.id < x.id
order by t.id desc
limit 3
Demo: http://sqlfiddle.com/#!9/7ffc4/2
It outputs the rows in descending order, but you can either live with that, or else put that query in a subquery and reverse the order.
Re your comment:
x in the above query is called a "correlation name" so we can refer to columns of the subquery as if they were columns of a table. It's required when you use a subquery as a table.
I chose the letter x arbitrarily. You can use anything you like as a correlation name, following the same rules you would use for any identifier.
You can also optionally define a correlation name for any simple table in the query (like mytable t above), so you can refer to columns of that table using a convenient abbreviated name. For example in t.id < x.id
Some people use the term "table alias" but the technical term is "correlation name".
I got a database that registers user actions and their geolocation.
Now I would like to fetch this data at the hand of the last action per user.
The table looks a bit like:
geoaction_id AUTO INCREMENT
geoaction_user
geoaction_creationdate (Y-m-d H:i:s)
geoaction_action
geoaction_lon
geoaction_lat
Now I would like to make a simple query that selects of all users the last item.
But LIMIT 0,1 just parses one row no matter what. (LOGICALLY!!)
Group by gives a little better result.
But how to get only the last item per user?
Try this, please provide the queries you have checked out so far, in order to assist you better.
SELECT geoaction_user, geoaction_action
FROM table-name
GROUP BY geoaction_user
ORDER BY geoaction_action DESC LIMIT 1
Working with sets:
SELECT
g.geoaction_user,
g.geoaction_action,
g.geoaction_creationdate,
g.geoaction_lat,
g.geoaction_lon
FROM
(
SELECT
geoaction_user,
MAX(geoaction_id) max_id
FROM
geoactions
GROUP BY geoaction_user
) s
JOIN
geoactions g
ON s.geoaction_user = g.geoaction_user
AND s.max_id = geoaction_id
The subquery generates a virtual table with the geoaction_id from the latest entry in the tabble for each user_id, then the table is joined to get the data belong to the latest id.
If you need to filter out some records place the where clause in the subquery
Whenever a query like
"select * from table where userid=xx" is done, the mysql fetches these values from
first row to last row of table.
But I want to select from last to first so that recently updated values are displayed first in the results.
I cannot do "select * from table where userid=xx order by time DESC" because there is no time column in table.
I just want recently updated items in the table displayed first.
$result= mysql_query("SELECT
(SELECT column FROM table WHERE [condition] ORDER BY column LIMIT 1) as 'first',
(SELECT column FROM table WHERE [condition] ORDER BY column DESC LIMIT 1) as 'last'");
$row=mysql_fetch_array($result);
echo $row['first'];
echo $row['last'];
If you have any auto-incrementing field you could sort by that desc.
You must provide a column to order by in order to guarantee results. So you will have to either change your table structure or make a decision on what to order by.
A hack would be to pull in the data in the order presented into an array, then start popping off the bottom of that array.
You either have to have a timestamp, or autoincrement id, or some other column that you want to sort by.
Just because you get rows in a certain order from a database when not using an ORDER BY clause, does not mean that they are guaranteed to be returned in that order. It also doesn't imply any order in the result set. You need a definitive field that you can use to ORDER BY, or you cannot do what you are wanting to do.
Some hack you can do for that if you don't have columns you can rely on:
SELECT * FROM (SELECT *,(#x:=#x+1) default_ordering FROM `table_name`, (SELECT #x:=0) t2) any_name ORDER BY default_ordering DESC