can anyone generate a query for me.
Lets say i have a table sales(saleID, date_of_sales, customerID, itemID, saleprice)
date_of_sales is the datetime field which stores the time of the sale.
customerID is self exlpaining tells to whom item was sold.
itemID is ID of the item sold.
saleprice is the price that the item was sold.
I want to construct a query which will give out the detail of the last purchase by each customers. this could be done by using date_of_sales.
Example table
saleID | date_of_sales | customerID | itemID | saleprice
101 | 2008-01-01 | C2000 | I200 | 650 |
102 | 2010-01-01 | C2000 | I333 | 200 |
103 | 2007-01-01 | C3333 | I111 | 800 |
104 | 2009-12-12 | C3333 | I222 | 100 |
this is the example data table, there are only two customer for simplicity.
customer C2000 did his last purchase
on 2010-01-01
customer C3333 did his last purchase
on 2009-12-12
I want to get a result like this
customerID | date_of_sales | itemID | saleprice
C2000 | 2010-01-01 | I333 | 200 |
C3333 | 2009-12-12 | I222 | 100 |
This might be what you are looking for...
SELECT *
FROM sales
WHERE sales.date_of_sales = (SELECT MAX(date_of_sales)
FROM sales s2
WHERE s2.customerID = sales.customerID);
There is a slight problem with it; if there were two sales on the same day to the same customer, you'll get two rows (unless your date-of-sales column includes the time as well). I think the same applies to the answer above, though.
Additionally, if you DO want to get results based on only a SINGLE entry of the maximum date, I would use the query by #Sachin Shanbhag above, but add a maximum sales ID value too... Since that would be implied as sequential, whichever was entered last would probably be the most recent.
SELECT S.* FROM
sales S
INNER JOIN
( SELECT
customerID,
MAX(date_of_sales) dos,
MAX(SalesID) maxSale
FROM
sales
GROUP BY customerID
) S2 ON S.customerID = S2.customerID
AND S.date_of_sales = S2.dos
AND S.SalesID = S2.maxSale
Related
I have a MySQL table named, "store_update_stock" to store purchase & issue of items. Order status column maintain the states, "purchase" or "issue" when need. Purchase quantity has denoted by plus values (eg:-10) & issue quantity has denoted by minus values (eg:- -2) in the table.
To get the purchase & issue summary I used the following query.
SELECT item_id, item_name, order_status, (CASE order_status
WHEN "issue" THEN store_update_stock_details.qty * (-1)
ELSE store_update_stock_details.qty
END) quantity FROM store_update_stock
And generated the expected output as follows :
+---------+-----------+--------------+----------+
| item_id | item_name | order_status | quantity |
+---------+-----------+--------------+----------+
| 1000 | A4 | purchase | 10 |
| 1001 | A3 | purchase | 5 |
| 1000 | A4 | issue | 2 |
| 1000 | A4 | issue | 3 |
| 1001 | A3 | purchase | 6 |
+---------+-----------+--------------+----------+
But I need to get further the balance of each items after performing purchases & issues by modifying the above query and get the output as follows :
+---------+-----------+---------+
| item_id | item_name | balance |
+---------+-----------+---------+
| 1000 | A4 | 5 |
| 1001 | A3 | 11 |
+---------+-----------+---------+
What can be done in my query to get the desired output. Can anyone helpme ?
It looks like all you might need is a simple aggregate sum and a group by:
select item_id, item_name, sum(quantity) as balance
from store_update_stock
group by item_id, item_name
maybe?
I am new at SQL and I need to write a query which returns list of orders that can be fulfilled with the items in the inventory.
Lets say the following table shows orders and required items to get them fulfilled.
------------------------------
| OrderID | Required Item No |
------------------------------
| ORD001 | Item007 |
| ORD001 | Item008 |
| ORD001 | Item009 |
| ORD002 | Item008 |
| ORD002 | Item009 |
| ORD002 | Item012 |
| ORD003 | Item008 |
| ORD003 | Item014 |
So In order to get fulfilled,
ORD001 needs Item007,Item008,Item009
ORD002 needs Item008,Item009,Item012
ORD003 needs Item008,Item014
And Lets assume this table is show my inventory
--------------------------
| Item Unique Id |Item No |
--------------------------
| 001 | Item007|
| 002 | Item008|
| 003 | Item008|
| 004 | Item012|
| 005 | Item009|
| 006 | Item014|
| 007 | Item015|
In this case, the query should returns ORD001 and ORD003. Can somebody help me on this?
My first attempt
Following query returns my inventory
SELECT ItemNo, COUNT(ItemNo) AS QTY
FROM InventoryTable
GROUP BY ItemNo
------------------------------
| ItemNo | QTY |
------------------------------
| Item007| 1 |
| Item008| 2 |
| Item009| 1 |
| Item012| 1 |
| Item014| 1 |
| Item015| 1 |
This query returns list of required item for a spesific order
SELECT ItemNo, COUNT(ItemNo) AS QTY
FROM OrdersTable
Where OrderID ='ORD003'
Group By ReqItemNo
------------------------------
| ItemNo | QTY |
------------------------------
| Item008 | 1 |
| Item0014| 1 |
I could not find a way to subtract item quantities between these two tables and make the subtraction for each order and return available orders.
Thanks to #Gordon Linoff for his suggestion
select t1.OrderID
from t1
left join inventory i
on t.required_item_no = i.item_no
group by t1.OrderId
having count(*) = count(i.item_no)
This query seems correct but it returns ORD001,ORD002,ORD003 for the example above. When the Item009 is assigned to ORD001, because there will be no Item009 anymore, the query should not fulfill ORD002.
Basically, you want the order where the required items for an order are in inventory. This will provide that list, but it ignores other order requirements. IOW, if the first order depletes an item required for the 2nd order, it won't pick up on that.
SELECT
t1.OrderID,
COUNT(DISTINCT t1.required_item_no) as `required_items`,
COUNT(DISTINCT i.item_no) as `items_on_hand`
FROM t1
LEFT JOIN inventory i
ON t1.required_item_no = i.item_no
GROUP BY t1.OrderId
HAVING `required_items` = `items_on_hand`;
UPDATE
I see that the query above fails to consider the quantity of each inventory item, and would include items that exist with a zero quantity. The following update should address this issue.
Because of the way order items and inventory are stored, instead of directly referencing the tables, I've used a sub-select in the following. Performance will be an issue when a large number of items are added to the table. You may want to reconsider how the quantities are stored and have one row per inventory item with a column to store the quantity on hand. Same for the order table.
SELECT
t1.OrderID,
COUNT(DISTINCT t1.required_item_no) as `required_items`,
COUNT(DISTINCT i.item_no) as `items_on_hand`
FROM (
SELECT
OrderID,
required_item_no,
COUNT(*) as `QTY`
FROM OrdersTable
GROUP BY OrderID, required_item_no
) t1
LEFT JOIN (
SELECT
item_no,
COUNT(*) as `QTY`
FROM inventory
GROUP BY item_no
) i
ON t1.required_item_no = i.item_no AND
i.QTY >= t1.QTY
GROUP BY t1.OrderId
HAVING `required_items` = `items_on_hand`;
In my database I have a table, payers_payments, consisting of some foreign keys (payer_id, payment_id) and some pivot fields (amount, pays).
| id | payer_id | payment_id | amount | pays |
|----|----------|------------|--------|------|
| 1 | 1 | 1 | 20 | 0 |
| 2 | 2 | 1 | 23 | 1 |
| 4 | 1 | 2 | 14 | 1 |
| 5 | 2 | 2 | 17 | 1 |
| 6 | 1 | 3 | 10 | 1 |
| 7 | 2 | 3 | 0 | 0 |
Each row represents a contribution a payer made towards a payment. The pays field specifies whether that payer should be included in the payment.
The total cost of a payment is the sum of amount for a given payment_id. So if I wanted to see how much payment 2 cost I would run:
SELECT SUM(amount) AS sumOfPayment
FROM payers_payments
WHERE payment_id=2;
Likewise the total amount a given payer (say, payer 1) has contributed is:
SELECT SUM(amount) AS sumOfPayment
FROM payers_payments
WHERE payer_id=1;
Now, what I want to do is use the concept of fair share. Fair share is the total cost of the payment divided by the number of payers who have pay=1 for that payment. The simplest way I can express this is with a sub-query:
SELECT SUM(payers_payments.amount) / (SELECT count(*)
FROM payers_payments
WHERE pays
AND payers_payments.payment_id = 3
) AS FairShare
FROM payers_payments
WHERE payment_id=3
GROUP BY
payers_payments.payment_id;
For a given payer and payment their fair share is defined as:
SELECT IF(pays, FairShare, 0) as payerFairShare
FROM payers_payments
WHERE payer_id = 1
AND payment_id=3; --FairShare is the query as above
My question is that I want a query to get the total fair share for each payer based on the fair share of each payment and whether or not they are included in the payment. (If pays=false then their fair share is 0)
Based on the above data this is the kind of result I'm after for the 2 payers:
| payer_id | total_paid | fair_share |
|----------|------------|------------|
| 1 | 44 | 25.5 |
| 2 | 40 | 58.5 |
Is there a way to achieve this in a single query or must I do some looping of result sets?
I am agnostic on RDMS but something MySQL-like is good.
I would start by writing a query that works what a single share of a payment is. That is, per payment_id, the sum of all the amounts, divided by the number of people it needs to pay. That result can then be joined back to the original data.
SELECT
payers_payments.payer_id,
SUM(payers_payments.amount ) AS total_paid,
SUM(payers_payments.pays * payments.single_share) AS fair_share
FROM
payers_payments
INNER JOIN
(
SELECT
payment_id,
SUM(amount) / SUM(pays) AS single_share
FROM
payers_payments
GROUP BY
payment_id
)
AS payments
ON payers_payments.payment_id = payments.payment_id
GROUP BY
payers_payments.payer_id
It will be of benefit to have indexes on both (payment_id) and (payer_id).
It will be of benefit to have the amount field in a DECIMAL data-type, though you need to consider what you want to do with rounding. (A total payment of 10.00 needs to be divided three ways, 3.33 each and then what do you want to happen to the spare 0.01?)
I have two tables, invoices and deposits.
They look a bit like this:
INVOICES
id | paymentType | grossTotal | dateTime
1 | Cash | 1000 | UNIX TIME
2 | Card | 1350 | UNIX TIME
3 | Card | 1250 | UNIX TIME
4 | Card | 750 | UNIX TIME
DEPOSITS
id | paymentType | invNo | dateTime | amount
1 | Cash | 1 | UNIX TIME | 150
2 | Card | 2 | UNIX TIME | 350
The deposits are always past dates, and the invoice dates will be, for example today, so I want to determine the balance paid today on an invoice, ie, invoices.grossTotal - deposits.amount, and list by payment Type.
So, in the table example above, there is £850 would have been paid on Invoice 1 and £1000 on invoice 2, this is simple to achieve with one or two rows of each, but when grouping payment types and deposit invoices I am stuck...
SELECT
invoices.id,
sum(grossTotal)-IFNULL(depositsCheck.previouslyPaid,0) as todayTotal,
depositsCheck.previouslyPaid, sum(grossTotal) as grossTotal
FROM `invoices`
LEFT JOIN (SELECT SUM(amount) as previouslyPaid, invNo
FROM deposits
GROUP BY invNo) depositsCheck ON depositsCheck.invNo=invoices.id
GROUP BY invoices.paymentType ORDER BY id DESC
The SQL Query above, will work for the item paid for with CASH, but not for the Card payments, because, grouping invoices.paymentType means that the id column from the invoices table is no longer correct, so the JOIN fails if this row has an id to which no deposit relates.
How can I run a query as above, but ensuring that I can join the deposits table on any instance of an invoice, grouped by payment type that matches the grouped column id records?
I am using mySql, so please post joins that MySql can do! :D
The problem is that when you use GROUP BY, you can only SELECT aggregates and the columns you have grouped on.
invoices.id is a column you tried to select, but did not group. I think you probably want to add this column to the GROUP BY clause.
SELECT
invoices.id,
sum(grossTotal)-IFNULL(depositsCheck.previouslyPaid,0) as todayTotal,
depositsCheck.previouslyPaid, sum(grossTotal) as grossTotal
FROM `invoices`
LEFT JOIN (SELECT SUM(amount) as previouslyPaid, invNo
FROM deposits
GROUP BY invNo) depositsCheck ON depositsCheck.invNo=invoices.id
GROUP BY invoices.paymentType, invoices.id ORDER BY id DESC
For the example tables you gave, it will probably give:
id | paymentType | grossTotal | dateTime | previouslyPaid
1 | Cash | 1000 | UNIX TIME | 150
2 | Card | 1350 | UNIX TIME | 350
3 | Card | 1250 | UNIX TIME | 0
4 | Card | 750 | UNIX TIME | 0
But in general, you will have something like:
id | paymentType | grossTotal | dateTime | previouslyPaid
1 | Cash | 1000 | UNIX TIME | 150
1 | Card | 1000 | UNIX TIME | 300
2 | Cash | 1350 | UNIX TIME | 350
2 | Card | 1350 | UNIX TIME | 350
Where you can see above, for invoice 1, 150 was paid in cash, and 300 was paid by card.
I am trying to improve the fields name to be more obvious what it means.. is the fields name ok? or what can be changed to make it more obvious?
mysql> select * from order_items;
+----+----------+--------+----------+------------+-------+
| id | order_id | name | quantity | item_price | total |
+----+----------+--------+----------+------------+-------+
| 1 | 5 | Item 1 | 2 | 3.00 | 6.00 |
| 2 | 5 | Item 2 | 1 | 2.00 | 2.00 |
+----+----------+--------+----------+------------+-------+
mysql> select * from orders;
+----+---------+---------+-----------------+---------------+----------------+----------+---------------+------------+----------------+------------+----------------------+--------------------+--------------------+----------------------+
| id | shop_id | user_id | shipping_method | shipping_fees | payment_method | card_fee | commision_fee | item_total | customer_total | shop_total | shop_total_remaining | our_commission_net | our_commission_vat | our_commission_gross |
+----+---------+---------+-----------------+---------------+----------------+----------+---------------+------------+----------------+------------+----------------------+--------------------+--------------------+----------------------+
| 5 | 29 | 9 | delivery | 1.00 | card | 0.50 | 13 | 8.00 | 9.50 | 9.00 | 7.83 | 1.17 | 0.23 | 1.40 |
+----+---------+---------+-----------------+---------------+----------------+----------+---------------+------------+----------------+------------+----------------------+--------------------+--------------------+----------------------+
Fields name description:
item_total Total cost from order_items.order_id = 5
customer_total Total cost for customer to pay (item_total + card_fee + shipping_fee)
shop_total Total order for the shop (item_total + shipping_fees)
shop_total_remaining Total remaining to pay back to shop (shop_total - our_commission_net)
our_commission_net Commission I will make (commission_fee * shop_total / 100)
our_commission_gross Commission inc VAT (our_commission_net + our_commission_vat)
Did I add unnecessary fields?
I used PHP to calculate the cost.
I can see you've actually added many fields that where not necessary. Think of it this way: If you can explain how to calculate a field by applying any operations to other fields, then it is a calculated field.
Those fields shouldn't be part of a minimalistic design as they can be obtained by operating over other fields. Let's go for the most complex example in your tables.
If you wanted to get the total of all the items for an order in your example you would just select the item_total field. But what happens if it wasn't there? Could you still get that number? Yes. This is how:
select sum(oi.total) from order_items oi
inner join order o on (oi.order_id = o.id)
where (o.id = 5)
Now, we've got rid of one field, but can we remove the order_items.total field and still get this result? Yes. Because it is also a calculated field. This is how:
select sum(oi.quantity * oi.item_price) from order_items oi
inner join order o on (oi.order_id = o.id)
where (o.id = 5)
Applying a similar pattern you can get rid of all the fields you've mentioned. And then you'll have a minimal design.
One thing that worths mentioning is that calculating fields is more complex than just querying the value so they are more expensive in terms of CPU and HD usage. The advantage of calculated fields is that you avoid data redundancy and save a bit of space too :)