I plan to make two with queries that make two temporary tables, one which gives the sum of the remaining loan payments, and one that gives the sum of all the transactions in the table. I've tested the two with statements and they work by themselves, however trying to perform a select query with them only seems to return errors.
WITH RemainingLoans AS(SELECT SUM(TIMESTAMPDIFF(MONTH, l.NextPayment, l.FullPaymentConfirmed) * l.MonthlyPaymentRate) AS RemainingPayments FROM loans AS l);
WITH CurrentBalances AS(SELECT SUM(t.amount) AS allBalances FROM transactions AS t);
SELECT l.RemainingPayments - b.allBalances AS TotalOutstandings FROM RemainingLoans AS l, CurrentBalances AS b;
The first with is called RemainingLoans with one attribute RemainingPayments, and the second with is called CurrentBalances with one attribute allBalances. To my knowledge these should work like tables which is why I attempted my select clause on the third line, however I am currently getting syntax errors. Is there a correct way to format my select statement?
This should be a single statement, not multiple statements.
The fiddle
WITH list elements are separated by a comma. There's only one WITH keyword at the beginning of the list.
The semicolon goes at the end of the entire statement, not after the WITH list elements.
Here's the adjusted statement:
WITH RemainingLoans AS (
SELECT SUM(TIMESTAMPDIFF(MONTH, l.NextPayment, l.FullPaymentConfirmed) * l.MonthlyPaymentRate) AS RemainingPayments
FROM loans AS l
)
, CurrentBalances AS (
SELECT SUM(t.amount) AS allBalances
FROM transactions AS t
)
SELECT l.RemainingPayments - b.allBalances AS TotalOutstandings
FROM RemainingLoans AS l
, CurrentBalances AS b
;
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'm trying to show staff_code, staff_name and dept_name for those who have taken one book.
Here's my query:
SELECT SM.STAFF_CODE,SM.STAFF_NAME,DM.DEPT_NAME,BT.BOOK_CODE
FROM STAFF_MASTER SM,DEPARTMENT_MASTER DM,BOOK_TRANSACTIONS BT
WHERE SM.DEPT_CODE =DM.DEPT_CODE
AND SM.STAFF_CODE = (
SELECT STAFF_CODE
FROM BOOK_TRANSACTIONS
HAVING COUNT(*) > 1
GROUP BY STAFF_CODE)
It gives the error:
single-row subquery returns more than one row.
How to solve this?
Change = to IN:
WHERE SM.STAFF_CODE IN (SELECT ...)
Because the select returns multiple values, using equals won't work, but IN returns true if any of the values in a list match. The list can be a hard-coded CSV list, or a select with one column like your query is.
That will fix the error, but you also need to remove BOOK_TRANSACTIONS from the table list and remove BOOK_CODE from the select list.
After making these changes, your query would look like this:
SELECT SM.STAFF_CODE,SM.STAFF_NAME,DM.DEPT_NAME
FROM STAFF_MASTER SM,DEPARTMENT_MASTER DM
WHERE SM.DEPT_CODE =DM.DEPT_CODE
AND SM.STAFF_CODE IN (
SELECT STAFF_CODE
FROM BOOK_TRANSACTIONS
HAVING COUNT(*) > 1
GROUP BY STAFF_CODE)
I recommend learning the modern (now over 25 year old) JOIN syntax.
I need to combined 2 tables with the same ids in it but i can't
SELECT stat.user_id, user.username,
SUM(stat.vertrag) AS vertrag,
SUM(stat.zubehoer) AS zubehoer,
SUM(stat.privat) AS privat,
SUM(stat.service) AS service,
SUM(stat.bs_vertrag) AS bus
FROM statistics stat
join users user on stat.user_id = user.uid
WHERE stat.user_id != '0' AND stat.datum LIKE '%$month%'
GROUP BY stat.user_id
UNION
SELECT bew.user_id, stat.user_id, user.username,
SUM(case when bew.log = 'inv_imei'
THEN
1
ELSE
0
END) AS inv
FROM user_bewegungen bew
JOIN users user ON user.uid = bew.user_id
JOIN statistics stat ON bew.user_id = stat.user_id
WHERE bew.date LIKE '%$month%'
GROUP BY bew.user_id
ORDER BY vertrag DESC
I am dont know how to go now.....
The first select is perfect, and works. now i have add a union because i need to add the row "log". Id's are also in it but i become the error
The used SELECT statements have a different number of columns
Can anyone help?
Each select statement needs to have the same number of columns. Your first one has 7:
SELECT
stat.user_id,
user.username,
SUM(stat.vertrag) AS vertrag,
SUM(stat.zubehoer) AS zubehoer,
SUM(stat.privat) AS privat,
SUM(stat.service) AS service,
SUM(stat.bs_vertrag) AS bus
Your second one has 4:
SELECT
bew.user_id,
stat.user_id,
user.username,
SUM(case when bew.log = 'inv_imei' THEN 1 ELSE 0 END) AS inv
You can select NULL in the second SELECT for those columns that aren't in the first one.
Make the two operands of the UNION isomorphic. Rename columns and/or create NULL-valued dummy columns as necessary to give them the same shape. FOR EXAMPLE, if we wanted to form the UNION of:
SELECT a, b, c
FROM table1
and:
SELECT d, e
FROM table2
we would logically pair those columns that are of the same types (in this case, let's assume that a and e are of the same type, and that b and d are of the same type) and add an extra NULL-valued column as the third projected attribute of the right-hand SELECT, as follows:
SELECT b, a, c
FROM table1
UNION
SELECT d AS b, e AS a, NULL as c
FROM table2
If such an approach seems confusing, you can use table views to simplify the expression. In the preceding example, you could have asserted a view atop table2:
CREATE VIEW t2view( b, a, c )
AS
SELECT d, e, NULL
FROM table2
and then formulated your UNION as:
SELECT b, a, c
FROM table1
UNION
SELECT *
FROM t2view
In UNION, the field numbers should be the same. Use like this:
SELECT stat.user_id, 0, user.username, ....
SELECT bew.user_id, stat.user_id, user.username, ...
or use something else, what you know, that is a missing field there.
The data types should be the same also.
You are using MySQL Union.
UNION is used to combine the result from multiple SELECT statements into a single result set.
The column names from the first SELECT statement are used as the column names for the results returned. Selected columns listed in corresponding positions of each SELECT statement should have the same data type. (For example, the first column selected by the first statement should have the same type as the first column selected by the other statements.)
Reference: MySQL Union
Your first select statement has 7 columns and second statement has 4.
You should have same number of column and also in same order in both statement.
otherwise it shows error or wrong data.
you can see this example
there are two queries both queries have the same number of columns.
column name can be different.
select 'row1' as column1,'row2' as column2
union
select 'row3' as column11,'row4' as column222
if you change columns count, it means in first query you are selecting 2 columns and in second query you are using 3 columns then it will through an error (The used SELECT statements have a different number of columns).
select 'row1' as column1,'row2' as column2
union
select 'row3' as column11,'row4' as column222 ,'rr' as t ;
run both queries you will see differnce.
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'