MYSQL Unknown Column in Query - mysql

I am looking to fetch sum of transactions grouping them by item ID. I am able to get desired result fron below query in Oracle DB but the same does not work in MYSQL.
Below error is what I am getting:
Unknown column 'tran.itemid' in 'on clause'
SELECT tran.itemid,
(SELECT SUM(tranitm.quandity)
FROM transactions_item tranitm
JOIN transactions tr
ON(tr.id = tranitm.transid and tranitm.itemid = tran.itemid)
where TR.TRANSTYPE = 1) Purchases,
(SELECT SUM(tranitm.quandity)
FROM transactions_item tranitm
JOIN transactions tr
ON(tr.id = tranitm.transid and tranitm.itemid = tran.itemid)
where TR.TRANSTYPE = 2 ) Sales,
(SELECT SUM(tranitm.quandity)
FROM transactions_item tranitm
JOIN transactions tr
ON(tr.id = tranitm.transid and tranitm.itemid = tran.itemid)
where TR.TRANSTYPE = 3 ) PurchasesRtn,
(SELECT SUM(tranitm.quandity)
FROM transactions_item tranitm
JOIN transactions tr
ON(tr.id = tranitm.transid and tranitm.itemid = tran.itemid)
where TR.TRANSTYPE = 4) SalesRtn
FROM transactions_item tran
GROUP BY tran.itemid
Schema :
CREATE TABLE transactions
( id INT, transtype INT,fromledger INT,
ledgerid INT,agentid INT, quandity FLOAT,rate FLOAT);
CREATE TABLE transactions_item
(transid INT, itemid INT,quandity FLOAT,rate FLOAT);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (1, 1, 1, 1, 1, 100, 1000);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (2, 2, 1, 1, 1, 10, 1200);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (3, 3, 1, 1, 1, 50, 1500);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (4, 4, 1, 1, 1, 120, 1300);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (5, 1, 1, 1, 1, 10, 1100);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (6, 2, 1, 1, 1, 12, 1400);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (7, 3, 1, 1, 1, 130, 1550);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (8, 4, 1, 1, 1, 110, 1700);
INsert into transactions_item (transid, itemid,quandity,rate) values (1, 1, 100, 1000);
INsert into transactions_item (transid, itemid,quandity,rate) values (2, 1, 10, 1200);
INsert into transactions_item (transid, itemid,quandity,rate) values (3, 1, 50, 1500);
INsert into transactions_item (transid, itemid,quandity,rate) values (4, 1, 120, 1300);
INsert into transactions_item (transid, itemid,quandity,rate) values (5, 1, 10, 1100);
INsert into transactions_item (transid, itemid,quandity,rate) values (6, 1, 12, 1400);
INsert into transactions_item (transid, itemid,quandity,rate) values (7, 1, 130, 1550);
INsert into transactions_item (transid, itemid,quandity,rate) values (8, 1, 110, 1700);
INsert into transactions_item (transid, itemid,quandity,rate) values (1, 2, 100, 1000);
INsert into transactions_item (transid, itemid,quandity,rate) values (2, 2, 10, 1200);
INsert into transactions_item (transid, itemid,quandity,rate) values (3, 2, 50, 1500);
INsert into transactions_item (transid, itemid,quandity,rate) values (4, 2, 120, 1300);
INsert into transactions_item (transid, itemid,quandity,rate) values (5, 2, 10, 1100);
INsert into transactions_item (transid, itemid,quandity,rate) values (6, 2, 12, 1400);
INsert into transactions_item (transid, itemid,quandity,rate) values (7, 2, 130, 1550);
INsert into transactions_item (transid, itemid,quandity,rate) values (8, 2, 110, 1700);

The ON clauses in the subqueries should be used to relate the tables being joined. Conditions that aren't part of the join should be in WHERE.
But there's a better way to do this than all those correlated subqueries.
SELECT tran.itemid,
SUM(IF(tr.transtype = 1, tran.quandity, 0)) AS Purchases,
SUM(IF(tr.transtype = 2, tran.quandity, 0)) AS Sales,
SUM(IF(tr.transtype = 3, tran.quandity, 0)) AS PurchasesRtn,
SUM(IF(tr.transtype = 4, tran.quandity, 0)) AS SalesRtn
FROM transactions_item AS tran
JOIN transactions AS tr ON tran.transid = tr.id
GROUP BY tran.itemid
DEMO
See need to return two sets of data with two different where clauses

Related

How to get the value of a different ID that is acquired during the SELECT statement?

I have created an entity tblPerson and from this entity I need to get the bGroup of t.adminID and the bGroup from the d.personID. I have tried the below query but it's not returning anything.
`
SELECT t.adminID, p.firstName, p.lastName, t.transID, t.transDate, t.donationID, p.bGroup, b.bankName, d.personID AS 'Donor ID', 'Donor BGroup'
FROM tblTrans t
JOIN tblAdmin a ON t.adminID = a.adminID
JOIN tblPerson p ON a.personID = p.personID
JOIN tblDonation d ON t.donationID = d.donationID
JOIN tblBank b ON d.bankID = b.bankID
WHERE 'Donor BGroup' IN
(SELECT p.bGroup
FROM tblPerson p
JOIN tblDonation d ON p.personID = d.personID
JOIN tblTrans t ON d.donationID = t.donationID);
`
When I execute the subquery, it gives me the bGroup of the d.personID, what do you think is going on, and maybe any alternatives, please?
Sample Data
INSERT INTO tblPerson (personID, firstName, lastName, bGroup)
VALUES ('1A', 'John', 'Doe', 'XY'),
('2A', 'Joe', 'Bishop', 'AB'),
('1B', 'Elly', 'James', 'OP'),
('2B', 'Andre', 'Butch', 'XY'),
('3A', 'Amy', 'Gree', 'AB'),
('3B', 'Alfred', 'Black', 'OP'),
('4C', 'James', 'Brown', 'XY');
INSERT INTO tblAdmin (adminID, personID, description)
VALUES (1, '1A', 'Whatever.'),
(2, '1B', ''),
(3, '4C', 'Anything.'),
(4, '1A', '');
INSERT INTO tblDonation (donationID, bankID, personID, donationDate)
VALUES (1, 1, '3B', '2018-12-27'),
(2, 1, '2A', '2022-12-28'),
(3, 2, '3A', '2022-03-23'),
(4, 2, '4C', '2022-06-19'),
(5, 3, '1B', '2022-08-19'),
(6, 3, '2B', '2022-08-08'),
(7, 3, '3B', '2022-07-20'),
(8, 2, '4C', '2022-11-26'),
(9, 1, '3B', '2022-11-26'),
(10, 2, '2A', '2022-01-16');
INSERT INTO tblBank (bankID, bankName)
VALUES (1, 'Bank 1'),
(2, 'Bank 2'),
(3, 'Bank 3');
INSERT INTO tblTrans (transID, transDate, donationID, adminID)
VALUES (1, '2022-12-31', 1, 1),
(2, '2022-01-01', 2, 1),
(3, '2022-05-23', 3, 2),
(4, '2022-05-23', 4, 2),
(5, '2022-07-09', 5, 3),
(6, '2022-08-20', 6 4),
(7, '2022-12-27', 7,4);
Sample ERD Diagram
Expected Output
Example: 1, John, Doe, 1, 2022-12-31, 1, XY, Bank 1, 3B, OP.
Your WHERE 'Donor BGroup' IN (SELECT...) clause evaluates to WHERE false, because you don't have any rows with that value in tblPerson.bGroup. So, your SELECT statement's result set is empty.
It's hard to puzzle out your requirement from your question.
I managed to find the solution. Since I needed to call the same table twice with different IDs I had to create two aliases and JOIN the table twice, like so:
SELECT t.adminID, person.firstName, person.lastName, t.transID, t.transDate, t.donationID, person.bGroup, b.bankName, donor.personID AS 'Donor ID', donor.bGroup AS 'Donor BGroup'
FROM tblTrans t
JOIN tblAdmin a ON t.adminID = a.adminID
JOIN tblPerson person ON a.personID = person.personID
JOIN tblDonation d ON t.donationID = d.donationID
JOIN tblPerson donor ON
JOIN tblBank b ON d.bankID = b.bankID;

Write a query that returns the sum of the sales by month and year - SQL

I'm stuck on getting the sales months to add together instead of show up as separate lines. Here's the question:
Write a query that returns the sum of the sales by month and year. There will be only two columns returned “Month Year” and “Sales”. Format the Sales with a dollar sign and two decimal places. List the sales amount high to low.
My query:
SELECT date_format(salesdate, '%M,%Y') AS 'Month Year', CONCAT('$', salesamt) AS 'Sales'
FROM sales
GROUP BY invoiceid
ORDER BY salesamt DESC;
I'm pretty sure the group by is the issue, but none of the other columns work. Any help would be greatly appreciated.
Table:
CREATE TABLE sales (
invoiceid INT PRIMARY KEY,
depid INT,
salesamt DECIMAL(10,2),
salesdate DATETIME
);
Values:
insert into sales values (101, 2, 2111.02, '20160102');
insert into sales values (102, 2, 421.00, '20160202');
insert into sales values (103, 2, 675.00, '20160202');
insert into sales values (104, 2, 4355.00, '20160302');
insert into sales values (105, 2, 975.00, '20160304');
insert into sales values (106, 2, 1021.00, '20160402');
insert into sales values (107, 2, 2106.00, '20160425');
insert into sales values (108, 2, 2799.81, '20160501');
insert into sales values (109, 2, 4335.75, '20160502');
insert into sales values (110, 2, 12006.00, '20160521');
insert into sales values (111, 2, 5220.00, '20160602');
insert into sales values (112, 2, 7198.02, '20160618');
insert into sales values (113, 2, 4795.00, '20160625');
insert into sales values (114, 2, 5341.00, '20160706');
insert into sales values (115, 2, 5795.00, '20160718');
insert into sales values (116, 2, 6400.00, '20160725');
insert into sales values (117, 2, 14795.00, '20160812');
insert into sales values (118, 2, 43395.00, '20160825');
insert into sales values (119, 2, 47595.00, '20160914');
insert into sales values (120, 2, 46795.00, '20160930');
insert into sales values (121, 2, 6223.00, '20161010');
insert into sales values (122, 2, 7702.00, '20161012');
insert into sales values (123, 2, 11292.00, '20161107');
insert into sales values (124, 2, 33211.00, '20161126');
insert into sales values (125, 2, 16430.00, '20161206');
insert into sales values (126, 2, 87010.00, '20161221');
insert into sales values (127, 2, 2111.02, '20170102');
insert into sales values (128, 2, 421.00, '20170202');
insert into sales values (129, 2, 675.00, '20170202');
insert into sales values (130, 2, 4355.00, '20170302');
insert into sales values (131, 2, 975.00, '20170304');
insert into sales values (132, 2, 1021.00, '20170402');
insert into sales values (133, 2, 2106.00, '20170425');
insert into sales values (134, 2, 2799.81, '20170501');
insert into sales values (135, 2, 4335.75, '20170502');
insert into sales values (136, 2, 12006.00, '20170521');
insert into sales values (137, 2, 5220.00, '20170602');
insert into sales values (138, 2, 7198.02, '20170618');
insert into sales values (139, 2, 4795.00, '20170625');
insert into sales values (140, 2, 5341.00, '20170706');
insert into sales values (141, 2, 7004.00, '20170718');
insert into sales values (142, 2, 14991.00, '20170725');
insert into sales values (143, 2, 34076.00, '20170812');
insert into sales values (144, 2, 47950.00, '20170825');
insert into sales values (145, 2, 40795.00, '20170914');
insert into sales values (146, 2, 41795.00, '20170930');
insert into sales values (147, 2, 47295.00, '20171010');
insert into sales values (148, 2, 47395.00, '20171012');
insert into sales values (149, 2, 41795.00, '20171107');
insert into sales values (150, 2, 47895.00, '20161126');
insert into sales values (151, 2, 87666.00, '20161206');
insert into sales values (152, 2, 9401.00, '20161221');
Try this
select concat('$',sum(a.Sales)) sum, a.Month_Year
from
(SELECT date_format(salesdate, '%M,%Y') AS 'Month_Year', salesamt AS 'Sales' FROM sales) a
group by a.Month_Year
order by sum(a.Sales) desc;
About your query...
I think the invoiceId is unique.
It is the reason why your group by is useless.

Selecting only the first two items from and order

I need you help regarding something, i have 3 tables ORDERS, ORDER_ITEM, ORDER_ITEM_LINE.
CREATE TABLE orders
(`id` int, `date` datetime)
;
INSERT INTO orders
(`id`, `date`)
VALUES
(78, '2017-01-03 00:00:00'),
(79, '2017-02-03 00:00:00'),
(80, '2017-03-03 00:00:00'),
(81, '2017-04-03 00:00:00'),
(82, '2017-05-03 00:00:00'),
(83, '2017-06-03 00:00:00'),
(84, '2017-07-03 00:00:00')
;
CREATE TABLE order_item
(`id` int, `fk_o_id` int, `sku` int)
;
INSERT INTO order_item
(`id`, `fk_o_id`, `sku`)
VALUES
(10, 78, 123),
(11, 79, 124),
(12, 79, 125),
(13, 80, 126),
(14, 82, 127),
(15, 82, 128),
(16, 82, 129)
;
CREATE TABLE order_item_line
(`id` int, `fk_oi_id` int, `line_id` int)
;
INSERT INTO order_item_line
(`id`, `fk_oi_id`, `line_id`)
VALUES
(33, 10, 1),
(34, 11, 1),
(35, 12, 2),
(36, 13, 1),
(37, 14, 1),
(38, 15, 2),
(39, 16, 3)
;
I would like to display all orders with 2 or more than 2 items but only first two so it will be line_id - 1 and 2.
The outcome should look like:
Outcome
If you have any ideas, thank you in advance.
To get the result you require, you will need to create another table. In this example I created a table called TESTQUERY and inserted data to count how many times the orders id appeared
Table creation
CREATE TABLE TESTQUERY
(`id` int, `count` int)
Data into the test table
INSERT INTO TESTQUERY
(
SELECT o.id, COUNT(o.id) as count FROM orders o
JOIN order_item oi ON oi.fk_o_id = o.id
JOIN order_item_line oil ON oil.fk_oi_id = oi.id
GROUP BY o.id
)
I then queried against all for databases using the query below and it returned your desired outcome
SELECT o.id, oi.sku, oil.line_id FROM orders o
JOIN order_item oi ON oi.fk_o_id = o.id
JOIN order_item_line oil ON oil.fk_oi_id = oi.id
JOIN TESTQUERY t ON t.id = o.id
WHERE t.count > 1 AND oil.line_id < 3
I hope this helps

SQL - adding total by searching for another value relating to the amount

been given this problem to solve
Write a function to get the payment sales figures from any given shop. The shop should be searched for by name.
i have this so far
SELECT shopname SUM ( amount ) AS sales
FROM frs_Shop, frs_Payment
WHERE shopname = "shop name"
i have the amount to add up but when i go to compile it adds up every amount in this table
INSERT INTO frs_Payment
(payid, amount, paydatetime, empnin, custid, pstatusid, ptid)
values
(101, "3.99", "2015-10-26 16:26:15", "NIN001", 1, 1, 1),
(95, "15.96", "2015-09-24 16:26:15", "NIN001", 1, 1, 1),
(102, "3.99", "2015-10-11 13:25:31", "NIN003", 2, 1, 1),
(11, "11.97", "2015-06-12 19:37:59", "NIN010", 3, 1, 1),
(7, "11.97", "2015-04-11 12:41:28", "NIN010", 3, 2, 4),
(8, "7.98", "2015-05-05 22:49:02", "NIN010", 3, 1, 1),
(32, "15.96", "2015-07-19 02:26:49", "NIN024", 5, 2, 4),
(83, "7.98", "2015-08-20 16:21:08", "NIN011", 5, 2, 4),
(6, "15.96", "2015-03-04 10:51:03", "NIN027", 6, 2, 4),
(17, "3.99", "2015-10-03 01:06:15", "NIN028", 6, 1, 1),
(39, "11.97", "2015-03-24 20:03:05", "NIN027", 6, 1, 1),
(103, "3.99", "2015-10-27 14:45:11", "NIN009", 7, 1, 1),
(62, "15.96", "2015-10-12 14:23:23", "NIN001", 8, 1, 1),
i want it to only add up the ones i specify with the empnin
You can use an explicit join, and a GROUP BY. I made an assumption on the primary/foreign key relationship between frs_Shop and frs_Payment.
SELECT s.shopname
, p.empnin
, SUM ( p.amount ) AS sales
FROM frs_Shop s
INNER JOIN frs_Payment p on s.empnin = p.empnin
WHERE s.shopname = "shop name"
GROUP BY s.shopname, p.empnin

SELECT data based on result of previous row in table

I have a database of students.
CREATE TABLE classlist
(`id` int, `studentid` int, `subjectid` int, `presentid` int)
;
CREATE TABLE student
(`id` int, `name` varchar(4))
;
CREATE TABLE subject
(`id` int, `name` varchar(4))
;
CREATE TABLE classStatus
(`id` int, `name` varchar(8))
;
INSERT INTO classlist
(`id`, `studentid`, `subjectid`, `presentid`)
VALUES
(1, 111, 1, 1),
(2, 222, 3, 0),
(3, 333, 2, 1),
(4, 111, 4, 1),
(5, 111, 1, 0),
(6, 222, 3, 0),
(7, 333, 2, 1),
(8, 111, 4, 1),
(9, 111, 2, 0),
(10, 111, 4, 1),
(11, 111, 1, 1),
(12, 333, 3, 1),
(13, 333, 2, 1),
(14, 333, 3, 1)
;
INSERT INTO student
(`id`, `name`)
VALUES
(111, 'John'),
(222, 'Kate'),
(333, 'Matt')
;
INSERT INTO subject
(`id`, `name`)
VALUES
(1, 'MATH'),
(2, 'ENG'),
(3, 'SCI'),
(4, 'GEO')
;
INSERT INTO classStatus
(`id`, `name`)
VALUES
(0, 'Absent'),
(1, 'Present')
;
And I have a query which shows how many times they have been present or absent.
SELECT
studentid,
students.name AS NAME,
SUM(presentid = 1) AS present,
SUM(presentid = 0) AS absent
FROM classlist
INNER JOIN student as students ON classlist.studentid=students.id
GROUP BY studentid, NAME
See this fiddle below.
http://sqlfiddle.com/#!2/fe0b0/1
There seems to be a trend from looking at this sample data that after someone attends subjectid 4 they are often not coming to the next class. How can I capture this in a query. I want to ONLY show data WHERE last subjectid =4. So in my sample data rows matching my criteria would be.
(5, 111, 1, 0),
(9, 111, 2, 0),
(11, 111, 1, 1),
as these rows are all the next row of a studentid who had a subjectid=4.
My output would be
| STUDENTID | NAME | PRESENT | ABSENT|
| 111 | John | 1 | 2 |
To get the next class for a student, use a correlated subquery:
select cl.*,
(select min(cl2.id) from classlist cl2 where cl2.studentid = cl.studentid and cl2.id > cl.id) as nextcl
from classlist cl
Plugging this into your query example tell you you who is present and absent for the next class:
SELECT students.id, students.name AS NAME,
SUM(cl.presentid = 1) AS present, SUM(cl.presentid = 0) AS absent,
sum(clnext.presentid = 1) as presentnext
FROM (select cl.*,
(select min(cl2.id) from classlist cl2 where cl2.studentid = cl.studentid and cl2.id > cl.id) as nextcl
from classlist cl
) cl INNER JOIN
student as students
ON cl.studentid = students.id left outer join
classlist clnext
on cl.nextcl = clnext.id
GROUP BY students.id, students.NAME
Add a where cl.subjectid = 4 to get the answer for subject 4.
I fixed the query. The SQLFiddle is k.
A quick and dirty solution could be to get the Classlist.Id for all lines where subjectid=4 (let's call them n) then select all the lines where Id = n+1