I am trying to calculate a due amount summing and grouping more amounts in table i_payment_history comparing then the result with the total "to_be_payed" amount saved in table pt_bookings. All involved fields are decimal(8,2), i have tryied with Cast becouse without is not working eather. The value "Due" is just the result of 'to_be_payed'-'payed'
so the first value in column "Due" should be 755,10-200,00=535,10 .
Why is "Due" calculating a wrong value? Txs !
SELECT i_payments_history.booking_id, Cast(SUM(amount)AS DECIMAL(8,2)) as payed, pt_bookings.booking_total, pt_bookings.booking_ref_no, (pt_bookings.booking_total - payed) as due
FROM `i_payments_history`
JOIN pt_bookings
on pt_bookings.booking_id= i_payments_history.booking_id
GROUP BY booking_id
see in below pic what the query is returning
Repeat the expression:
SELECT ph.booking_id, Cast(SUM(ph.amount) AS DECIMAL(8,2)) as payed, b.booking_total, b.booking_ref_no,
(b.booking_total - SUM(ph.amount)) as due
FROM `i_payments_history` ph JOIN
pt_bookings b
on b.booking_id = ph.booking_id
GROUP BY b.booking_id;
An alias cannot be used in the same select where it is defined. One alternative is to use a subquery; another is to repeat the expression. Your query did not return an error because one of your tables must have a column named payed.
Related
The question is about using a column (which is created in query) as where clause criteria.
There are 2 tables named transactions and transactionmovements.
In transaction, there are unique info for transaction like date, counterparty etc.
In transactionmovements, there are articles which is used in transaction. Such as product, quantity, price, etc. And transactionmovements has a 'transaction' column which references to transactions.id shows which transaction the movement belongs.
In the query, I created a totalPrice value with sum of quantity*price of each movement that belongs to a transaction.
Everything works perfectly but the last parameter of WHERE clause. If I delete "AND
totalPrice > 10" part, it gives me everything including totalPrice and totalQuantity of a transaction.
But if I place "AND totalPrice > 10" to the end, it returns following error:
-#1054 - Unknown column 'totalPrice' in 'where clause'
SELECT
`transactions`.id,
`transactions`.type,
`transactions`.date,
`transactions`.VAT,
`transactions`.currency,
`companies`.name AS counterparty,
COALESCE
(sum(`transactionmovements`.price*`transactionmovements`.quantity)
+(`transactions`.shippingQuantity*`transactions`.shippingPrice)) as totalPrice,
COALESCE
(sum(`transactionmovements`.quantity)) as totalQuantity
FROM
`transactions`
LEFT JOIN `companies` ON `transactions`.counterparty = `companies`.id
LEFT JOIN `transactionmovements` ON `transactions`.id=`transactionmovements`.transaction
WHERE ( `transactions`.type = 'p' OR `transactions`.type = 'r' OR `transactions`.type = 's' OR `transactions`.type = 't')
AND
(`transactions`.date BETWEEN IFNULL('','1900-01-01') AND IFNULL('2020-02-14',NOW()))
AND
totalPrice > 10
GROUP BY `transactions`.id
ORDER BY id desc
LIMIT 10
I tried using the whole math operation in WHERE clause, but no gains. I tried to use HAVING with WHERE but couldn't manage it.
The last solution I have is running it without filtering by totalPrice and store it into a php array. Then filter in array, but there I can't use LIMIT so array will be very big.
As per how SQL query are executed in the order that dictate SELECT is executed after WHERE, you can't use ALIAS in WHERE since it is unknown at the moment. Therefor, you should change every alias uses outside of SELECT to its definition.
As Thomas Jeriko suggested in comments, creating a view was exactly what I need.
First I create a virtual table with Create View.
CREATE VIEW transactionreportview
AS SELECT
transactions.id id,
transactions.type type,
transactions.date date,
transactions.VAT VAT,
transactions.currency currency,
transactions.counterparty counterparty,
(SUM(transactionmovements.price*transactionmovements.quantity)+transactions.shippingQuantity*transactions.shippingPrice) totalPrice,
SUM(transactionmovements.quantity) totalQuantity
FROM transactions transactions, transactionmovements transactionmovements
WHERE transactions.id = transactionmovements.transaction
GROUP BY transactions.id;
While the virtual table acts like a simple mysql table, I ran a new query in the table
SELECT * FROM transactionReportView WHERE ..."
Then after finishing my work with the virtual table, drop it
DROP VIEW transactionreportview
Okay so I have two tables:
hscust and hssales_rep
I need to create a view that shows me the reps fname and lname (as well as the customers) and show how much the customer is over on there credit balance.
This is the code I have:
CREATE VIEW OverLimit AS
SELECT
CONCAT(hssales_rep.last,hssales_rep.first) AS Rep,
CONCAT(hscust.last,hscust.first) AS Cust,
SUM(credit_limit - balance)
FROM hscust
INNER JOIN hssales_rep ON hscust.sales_rep = hssales_rep.repid
And it returns an empty result.
Any help is greatly appreciated!
salesrep table
cust table
A CREATE VIEW statement doesn't return a resultset.
A SELECT statement can return an empty resultset. But we'd expect the SELECT statement in your view definition to return either a single row, or throw an error.
I suggest you break this down a bit.
1) What problem is being solved by the CREATE VIEW statement. Why do you need a view?
2) Before you write a CREATE VIEW statement, first develop and test a SELECT statement that returns the required resultset. Do that before you put that into a view definition.
I also strongly recommend that you qualify all column references in the SELECT statement either with the table name or (preferably) a short table alias.
If you want to return a row for each Cust with an aggregate function (e.g. SUM) in your SELECT list, then add an appropriate GROUP BY clause to your SELECT statement.
It's not clear why we would want to use a SUM aggregate function.
The difference between "credit_limit" and "balance" would be the available (remaining) credit. A negative value would indicate the balance was "over" the credit limit.
SELECT CONCAT(r.last,r.first) AS Rep
, CONCAT(c.last,c.first) AS Cust
, c.credit_limit - c.balance AS available_credit
FROM hscust c
JOIN hssales_rep r
ON c.sales_rep=r.repid
ORDER
BY CONCAT(r.last,r.first)
, CONCAT(c.last,c.first)
, c.custid
If we only want to return rows for customers that are "over" their credit limit, we can add a WHERE clause.
SELECT CONCAT(r.last,r.first) AS Rep
, CONCAT(c.last,c.first) AS Cust
, c.credit_limit - c.balance AS available_credit
FROM hscust c
JOIN hssales_rep r
ON c.sales_rep=r.repid
WHERE c.credit_limit - c.balance < 0
ORDER
BY CONCAT(r.last,r.first)
, CONCAT(c.last,c.first)
, c.custid
Again, get a SELECT statement working (returning the required resultset) before you wrap it in a CREATE VIEW.
I find it really annoying to be not able to get the number of rows without having to use group by. I just need to get the "Total count" that my subquery returned.
Here is what my subquery looks like:
select sales_flat_order.increment_id, sales_flat_order.created_at, sales_flat_order.status, dispatch.dispatch_date,
DATEDIFF(TO_DATE(dispatch.dispatch_date), TO_DATE(sales_flat_order.created_at)) as delay
FROM
magentodb.sales_flat_order
LEFT OUTER JOIN erpdb.dispatch
ON
sales_flat_order.increment_id == dispatch.order_num
where
TO_DATE(created_at) >= DATE_SUB(current_date(),6)
AND
TO_DATE(created_at) <= DATE_SUB(current_date(), 3)
AND
sales_flat_order.status NOT IN ('canceled', 'exchange', 'rto', 'pending_auth', 'pending_payment' ,'partial_refund','refund', 'refund_cash', 'partial_refund_cash', 'holded')
)
AS TempFiltered
Now, I add 1 extra WHERE clause in my outer query so that it returned "lesser" number of rows, let's call this column y .
I then require to take percentage of x to y(i.e number of rows returned by outer query to subquery)
I do not wan to repeat my subquery only to get count of the rows. HOw do I get it?
This is what I have so far: But ofcourse it is wrong. I can not get count of all my rows without having to exclude select columns or using them in group by. HOw do I resolve this?
SELECT tempfiltered.delay, count(*) as countOfOrders,(100*count(*))/tempfiltered.Total) over () as percentage
FROM
(
select count(*) as Total, sales_flat_order.increment_id, sales_flat_order.created_at, sales_flat_order.status, dispatch.dispatch_date,
DATEDIFF(TO_DATE(dispatch.dispatch_date), TO_DATE(sales_flat_order.created_at)) as delay
FROM
magentodb.sales_flat_order
LEFT OUTER JOIN erpdb.dispatch
ON
sales_flat_order.increment_id == dispatch.order_num
where
TO_DATE(created_at) >= DATE_SUB(current_date(),6)
AND
TO_DATE(created_at) <= DATE_SUB(current_date(), 3)
AND
sales_flat_order.status NOT IN ('canceled', 'exchange', 'rto', 'pending_auth', 'pending_payment' ,'partial_refund','refund', 'refund_cash', 'partial_refund_cash', 'holded')
)
AS TempFiltered
Where
DATEDIFF(TO_DATE(TempFiltered.dispatch_date), TO_DATE(TempFiltered.created_at)) > 1
GROUP BY tempfiltered.delay
ORDER BY tempfiltered.delay
You could change the subquery into a SELECT INTO query, and put the data in a temporary table, and use that in the main query, and separately just select count(*) of that temporary table. That should pretty much satisfy your requirement.
I have the following query :
SELECT SUM(P_QTY)
FROM rankhistory
WHERE P_ID= '1'
AND RH_DATE>=1438556400
AND RH_DATE<1438642800
The above query returns 268
The result set contains two elements of P_QTY which are 160 and 108
Now what I want is be able to receive the difference instead of the sum, so what I want my query to return is 52, how can I achieve that through sql query?
Please note that the subquery can return more than one result, and the intended is get the total change. For example if query returns 168 160 150, the result should be 18.
There's no aggregate function for difference, but since you know exactly which rows to use, you can select each value as its own subquery, then subtract the two columns from one another in a single select statement.
SELECT a.op, b.op, a.op - b.op as diff
FROM (SELECT 10 as op) a
JOIN (SELECT 8 as op) b
Expressed in accordance with your schema, it would probably look like this:
SELECT a.op, b.op, a.op - b.op as diff
FROM (SELECT P_QTY as op FROM rankhistory WHERE P_QTY = 160) a
JOIN (SELECT P_QTY as op FROM rankhistory WHERE P_QTY = 108) b
To use this approach regularly in an application, however, you'll want to handle it based on ID's or something else easily selectable and meaningful.
It sounds like you want something else, though. Perhaps you're interested in the difference between max and min during a date range?
SELECT MAX(P_QTY) - MIN(P_QTY) as diff
FROM rankhistory
WHERE rh_date BETWEEN '1438556400' AND '1438642800'
SELECT quantity, materialTypeId ,
(SELECT typeName
FROM invTypes
WHERE TypeID IN (SELECT materialTypeId
FROM invTypeMaterials
WHERE typeId= 12743
)
) AS material
FROM invTypeMaterials
WHERE TypeID=12743
so this query gives me nice results except the column material. only shows me the first entry instead of giving the name of each row.
if i run these sql seperate they work and i do see what i want. i just need them combined into 2 columns.
what i want to do is, i query one table for data, one of the column has a value wich i want to convert to a name, and that is in another table and its linked by a unique TypeID
Chilly
May be this will work :
SELECT tm.quantity, tm.materialTypeId , t.typeName
FROM invTypeMaterials tm
INNER JOIN invTypes t ON t.TypeID = tm.materialTypeId
WHERE tm.TypeID=12743
If you want to lookup the materialTypeID's name for the current record, you must not use a separate subquery but use the materialTypeID value from the outer query.
This is called a correlated subquery:
SELECT quantity, materialTypeId,
(SELECT typeName
FROM invTypes
WHERE TypeID = invTypeMaterials.materialTypeId
) AS material
FROM invTypeMaterials
WHERE TypeID=12743