COUNT values in column and produce table of results mysql - php

To preface this question - I know I'm missing something really obvious here but it is Friday afternoon!
I'm trying to COUNT to number of times certain values appear within the same column and produce a table of the results.
Here's my code so far:
MYSQL
SELECT COUNT(order_status) as printed
FROM orders WHERE order_status = 'Printed Order'
UNION
SELECT COUNT(order_status) as charged
FROM orders WHERE order_status = 'Charged Order'
UNION
SELECT COUNT(order_status) as exchanged
FROM orders WHERE order_status = 'Exchanged Order'
UNION
SELECT COUNT(order_status) as refunded
FROM orders WHERE order_status = 'Refunded Order'
UNION
SELECT COUNT(order_status) as cancelled
FROM orders WHERE order_status = 'Cancelled Order'
GROUP BY order_status
Result of the above query
printed
-------
224
19190
593
2618
2899
The code is producing the correct figures, however, I would prefer the result to look as follows:
Desired result
printed - 224
charged - 19190
exchanged - 593
refunded - 2618
cancelled -2899
This way I can easily reference them via associative array call i.e. $order_status['printed']
Any help would be great.

Add a column specifying the type. The easiest way is to use group by:
select order_status, count(*)
from orders o
group by order_status;

If you use PDO, set the fetch mode to create associative arrays by default by:
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

try:
SELECT order_status, COUNT(order_status) as printed
FROM orders WHERE order_status = 'Printed Order'
GROUP BY order_status

Related

How to create new table for the output of DISTINCT COUNT to be distributed in rows, not in column?

My query displays the DISTINCT count of buyers with corresponding ticketserial#. I need to automatically calculate the SOLD and BALANCE column and save into the database either into the existing table (table1) with the rows that corresponds to the ticketserial. I've already exhausted my brain and did google many times but I just can't figure it out. So I tried another option by trying to create a new table into the database for the output of DISTINCT COUNT but I didn't find any sample query to follow, so that I could just use INNER JOIN for that new table with table1, with that the PRINTED, SOLD are in the same table, thus I can subtract these columns to obtain the values for the BALANCE column.
Existing table1 & table2 are records in the database via html form:
Table1
Ticket Serial Printed Copies SOLD(sold) Balance
TS#1234 50 ?(should be auto ?
TS#5678 80 ?(should be auto ?
(so on and so forth...)
Table2
Buyer Ticket Serial
Adam TS#1234
Kathy TS#1234
Sam TS#5678
(so on and so forth...)
The COUNT DISTINCT outputs the qty. of sold tickets:
<td> <?php print '<div align="center">'.$row['COUNT(ticketserial)'];?></td>
...
$query = "SELECT *, COUNT(ticketserial) FROM buyers WHERE ticketsold != 'blank' GROUP BY
ticketserial ";
It's COUNT output looks like this:
Ticket Serial------Distinct Count
TS#1234 7
TS#5678 25
(so on and so forth...)
I tried to update the SOLD column and BALANCE column by UPDATE or INSERT and foreach loop but only the first row in table was updated.
Table1
Ticket Serial Printed Copies Sold Balance
TS#1234 50 **7** 0
TS#5678 80 **0** 0
TS#8911 40 **0** 0
(so on and so forth...)
Note: The fieldname "sold" in table1 is not the same with the fieldname "ticketsold" in table2 as the former is quantity and the later is ticketserials.
Your question is a bit hard to follow. However this looks like a left join on a aggregate query:
select
t1.ticket_serial,
t1.printed_copies,
coalesce(t2.sold, 0) sold,
t1.printed_copies - coalesce(t2.sold, 0) balance
from table1 t1
left join (
select ticket_serial, count(*) sold
from table2
group by ticket_serial
) t2 on t2.ticket_serial = t1.ticket_serial
If you are looking to update the main table:
update table1 t1
left join (
select ticket_serial, count(*) sold
from table2
group by ticket_serial
) t2 on t2.ticket_serial = t1.ticket_serial
set
t1.sold = coalesce(t2.sold, 0),
t1.balance = t1.printed_copies - coalesce(t2.sold, 0)
I would not actually recommend storing the sold and balance in the main table - this is derived information that can be easily computed when needed, and would be tedious to maintain. If needed, you could create a view using the first above SQL statement, which will give you an always up-to-date perspective at your data.

Explain a MySQLi query that displays top 3 sold cars

I found the following mysqli query on the internet. It displays top 3 sold cars
//create conection with mysql database.
$conn = mysqli_connect("localhost","root","","cars");
//query
$select = "SELECT ord.*, sum(amount) as amt from orders as ord GROUP BY id_car order by amt desc limit 0,3";
$data = mysqli_query($conn,$select);
This query works fine but I would like if anyone can explain me this first section of the query: SELECT ord.*,
It seems like "ord" refers to orders but is it the same as saying: SELECT * FROM orders??
See table in the screenshot image
orders table
In the query there is orders as ord this gives the orders table an 'alias' of the orders table, so ord.* means orders.*
It is a bit redundant in this query to be honest, mainly used if there are multiople tables in a query :)
For this query you can simply do:
$select = "SELECT *, sum(amount) as amt from orders GROUP BY id_car order by amt desc limit 0,3";
Let's break it down:
a) Select all fields from table named ord which will be defined in c)
SELECT ord.*,
b) Select sum of column amount and name it amt
sum(amount) as amt
c) Use table orders for the query and define an alias name ord for that table, see a)
from orders as ord
It is same as select * from tableName,it will fetch all columns from table.But alias Name is given for the table. Using alias Name is best practices for joining the multiple tables.
since you are using single table you can do this also.
SELECT *, sum(amount) as amt from orders as ord GROUP BY id_car order by amt desc limit 0,3

MySQL query printing double records

All recorders in sales & purchase table are only entered Once. I have checked it carefully. However I wish to combine these two tables in such a way that both tables will be completely fetched. here is my query
note that timestamp column has mysql DATE format
Select
sales.ID as sid,
sales.saleHatsh,
sales.timestamp as sdate,
sales.gatePass as sGP,
sales.pname as sPN,
sales.description as sDES,
sales.balance as sbal,
purchase.ID as pid,
purchase.purchaseHatsh,
purchase.timestamp as pdate,
purchase.gatePass as pGP,
purchase.pname as pPN,
purchase.description as pDES,
purchase.balance as pbal
from sales,purchase
where sales.timestamp='2013-11-11' OR purchase.timestamp='2013-11-11'
here is the result of my query & sales & purchase table
Sales table only have 2 recorder
Purchase table only has 4 recorder
What is happening there is that you are not joining those tables in any way. so you are getting all the possible matches from those tables. Looking at the columns i don't think you want to JOIN, but probably you want a UNION instead:
SELECT
sales.ID AS id,
sales.saleHatsh AS hatsch,
sales.TIMESTAMP AS date,
sales.gatePass AS GatePass,
sales.pname AS pname,
sales.description AS Description,
sales.balance AS balance,
'SALE' AS transanctionType
FROM sales
WHERE sales.TIMESTAMP = '2013-11-11'
UNION
SELECT
purchase.ID,
purchase.purchaseHatsh,
purchase.TIMESTAMP,
purchase.gatePass,
purchase.pname,
purchase.description,
purchase.balance,
'PURCHASE'
FROM purchase
WHERE purchase.TIMESTAMP = '2013-11-11'
I added a column "transactionType" for you to identify which ones are sales or purchases.

Display result on specified column based on computed result

I have 2 db tables: Customer's Information and balances
Customer : Customer_ID, Name
Transaction: Customer_ID, Transaction_Name, Transaction_Amount... (Other columns but not necessary for my question)
Sample expected query output:
Customer_ID | Debit_Balance | Credit_Balance
1 | 500.00|
2 | | 300.00
Explanation: Customer 1 has 500.00 remaining balance and Customer 2 has 300.00 extra amount paid (This is usually (-) negative in nature)
Question:
How to do this in single query alone? I just wanted to generate report (like the above sample output) to display the result amount if positive as Debit_Balance and Credit_Balance for those negative balances then will process the result using Php.
UPDATE:
I used to do this processing of transaction amounts : I Sum up all the Transaction_Amount based on their Transaction_Name.
i.e.
Balance = (All Transaction_Name 'SALES' ) Less (-) (All
Transaction_Name 'PAYMENT')
But this will forced me to create dummy table as repository table for my report and more php condition to compare and INSERT.
I would use something like below:
SELECT C.customer_id, C.Name,
IF(SUM(Transaction_Amount)>0, SUM(Transaction_Amount),'') as Debit_Balance,
IF(SUM(Transaction_Amount)<=0, SUM(Transaction_Amount),'') as Credit_Balance
From Customer As C
LEFT JOIN Transaction As T ON C.customer_id = T.customer_id
GROUP BY T.customer_id
You want a single row of output for each customer, with the balance in either one column or another depending on whether it's positive or negative. Try (if we're using standard SQL):
select
subqry.Customer_ID
, case
when subqry.Balance >= 0 then subqry.Balance
end as Debit_Balance
, case
when subqry.Balance < 0 then subqry.Balance * -1
end as Credit_Balance
from (
select
Customer_ID
, sum(
case Transaction_Name
when 'SALES' then Transaction_Amount
when 'PAYMENT' then Transaction_Amount * -1
else null
end
) as Balance
from Transaction
group by Customer_ID
) as subqry
No need to join with the Customer table so far because we're not using the Customer Name anywhere.
I can't come up with anything easier than this:
SELECT c.customer_id, pos.amount debit_balance, neg.amount credit_balance
FROM customer c
LEFT JOIN (SELECT SUM(t.transaction_amount) amount, t.customer_id
FROM transaction t
WHERE t.transaction_amount > 0
GROUP BY t.customer_id) pos ON pos.customer_id = c.customer_id
LEFT JOIN (SELECT SUM(t2.transaction_amount) amount, t2.customer_id
FROM transaction t2
WHERE t2.transaction_amount < 0
GROUP BY t2.customer_id) neg ON neg.customer_id = c.customer_id
The first subquery sums up all positive values for each customer, while the second subquery sums up all the negative values. Then you get all customers and combine the two corresponding values into one result.

How to fetch the latest value by date in MySQL?

I have a table called payment which adds all the payment entries. I have field in payment table as customer_id which refers to the customer id in the customer table.
There is a field called flag where I store 1 or 0 based on their payment status. If they paid the full amount they flag will be 0 and if there is a balance the flag wil be 1
There is another field in payment table, added_on, which is a timestamp
I want to fetch out the latest added row of all the customer_id(in the payment table) who have flag 1(pending payment)
I tried fetching from the payment table like this
$rResult = mysql_query("select * from payment where flag='1'")
and then looped like this
while ($aRow=mysql_fetch_object($rResult))
{
//fetch out the customer id like this
$customer= $aRow->customer_id;
$pay_quer = mysql_query("select*from payment where customer_id='$customer'");
}
I know it is long to do this..is there any shorter way to do it with one query?
The results are not coming as I expected too. :(
SELECT p.*
FROM
payment AS p
JOIN
( SELECT customer_id
, MAX(added_on) AS max_added_on
FROM payment
WHERE flag='1'
GROUP BY customer_id
) AS g
ON g.customer_id = p.customer_id
AND g.max_added_on = p.added_on
ORDER BY p.added_on DESC
or (it's not clear what you want exactly nor how the flag is used). This will show different results, only those customers that their latest row in the payment has flag=1:
SELECT p.*
FROM
payment AS p
JOIN
( SELECT customer_id
, MAX(added_on) AS max_added_on
FROM payment
GROUP BY customer_id
) AS g
ON g.customer_id = p.customer_id
AND g.max_added_on = p.added_on
WHERE p.flag='1'
ORDER BY p.added_on DESC
I don't know the name of your table and fields but you get the point:
SELECT *
FROM payment
JOIN customer ON payment.customer_id = customer.customer_id
WHERE payment.flag = '1'
ORDER BY payment.added_on ASC;
This will contain all information about the customer related the payment sorted by the latest first.
Why not just use one select statement and loop through the results instead?
SELECT customer_id FROM payment WHERE flag='1' ORDER BY added_on DESC
Hopefully this will get all customers who have a balance in order of 'added_on'. =)
Like the answer below, you can also add an 'AND' to further cut down your results.
Simply order your select statement:
Select * from payment where flag = '1' and customer_id='$customer' order by YourTimeStempFieldHere
You can change the order direction by adding "desc" or "asc" behind your timestemp field.
You can also limit the result with the mysql LIMIT 0,1 operator. If you do that, you dont have to do a while loop.
use this to order by time added.
$rResult = mysql_query("select * from payment where flag='1' ORDER BY added_on DESC");
also
while ($aRow=mysql_fetch_object($rResult))
{
//fetch out the customer id like this
$customer= $aRow->customer_id;
$field2 = $aRow->field2 ;
$field3 = $aRow->field3 ;
$field3 = $aRow->field4 ;
}
there is no need for the second query. you have already got the values in the for loop

Categories