Fetch data regarding the total visits and revenue from customers - php

I have two tables, tbl_customers and tbl_transactions, where the fields of them are as follows:
**tbl_customer:**
c_id | c_name | age | Slab | gender | occupation | married | priority | ratings | contact | email | dob | anniversary
**tbl_transaction**
t_id | c_id | d_id | f_id | date_time | bill | member
The table tbl_transaction is a global table containing the transactions of all departments, differentiated by d_id.
Now I want to run a query that fetches c_id, total visits(means no of rows a c_id apppears in tbl_transaction), total revenue(means SUM(bill) of a particular c_id in) and the respective priority and ratings as it is in tbl_customer.
The query I was trying is :
Select c_id,
COUNT(cid) as tot_visit,
SUM(bill) as tot_revenue, priority, ratings
From tbl_customer c
inner join tbl_transaction t on c.c_id=t.c_id
Where $r_id='r1' AND $c_id='".$cid."'
group by c_id
So basicaly I want to display the total visits and revenue of each customer in customer table, but not sure what is the right way to do it.
Any help would be appreciated.
This is the error I am getting in SQL Engine

According to your error there are fields in both tables that have same name in your tables you need to give the table alias for the field, also when you are filtering on only one group then there is no need to use group by because you are using AND c.c_id='".$cid."' for a single group
Select c.c_id,
COUNT(c.cid) as tot_visit,
SUM(t.bill) as tot_revenue, c.priority, c.ratings
From tbl_customer c
inner join tbl_transaction t on c.c_id=t.c_id
Where $r_id='r1' AND c.c_id='".$cid."'
group by c.c_id

In general the query is fine. I would replace inner join with outer to process customers cho don't have transactions
Select c_id, COUNT(cid) as tot_visit, SUM(bill) as tot_revenue,
priority, ratings
From tbl_customer c LEFT JOIN tbl_transaction t on c.c_id=t.c_id
Where $r_id='r1' AND $c_id='".$cid."'
group by c_id

Related

Display the latest records from the right table and if records not available then at least show the records from left table

I have two table
tbl_register
tbl_societymyprofile
What I am doing is, I have to display the records from the tbl_register table and I have to display the latest record from the tbl_societymyprofile table.
I have a tried the below query.
SELECT *
FROM tbl_register AS r
LEFT JOIN tbl_societymyprofile AS m
ON r.reg_id = m.reg_id
WHERE r.reg_id =(SELECT Max(secretary_id) AS c_id
FROM tbl_societymyprofile
WHERE reg_id = 17
GROUP BY reg_id DESC)
AND r.is_active = 1
Also if the records are not available in the tbl_societymyprofile then at least display the records from the tbl_register table.
reg_id id is the primary id of the tbl_register table. As of now I have the records in the tbl_register table but don't have the records in the tbl_societymyprofile and i am getting the empty records
tbl_register
reg_id | name | mobileno | email
1 | abc |1234123455 | abc#gmail.com
2 | xyz |1234345455 | xyz#gmail.com
tbl_societymyprofile
secretary_id | reg_id | sec_name | sec_email | date_of_added
1 | 1 | ncx | ncx#gmail.com | 2021-06-09 15:54:35
2 | 1 | xbs | ncx#gmail.com | 2021-06-09 15:55:18
would you help me out with this?
If you need all records, try the following query:
SELECT r.*,
X.*
FROM tbl_register AS r
LEFT JOIN (SELECT sp.*
FROM tbl_societymyprofile sp
INNER JOIN (SELECT reg_id,
MAX(secretary_id) secretary_id
FROM tbl_societymyprofile
GROUP BY reg_id )T
ON sp.reg_id = T.reg_id
AND sp.secretary_id = T.secretary_id) X
ON r.reg_id = X.reg_id
If you need specific records, try the following query instead:
SELECT r.*,
X.*
FROM tbl_register AS r
LEFT JOIN (SELECT sp.*
FROM tbl_societymyprofile sp
INNER JOIN (SELECT reg_id,
MAX(secretary_id) secretary_id
FROM tbl_societymyprofile
GROUP BY reg_id )T
ON sp.reg_id = T.reg_id
AND sp.secretary_id = T.secretary_id) X
ON r.reg_id = X.reg_id
WHERE r.reg_id = 2
If your joined table order is not important (it usually isn't important) then maybe you should try something like:
SELECT * FROM tbl_register t LEFT JOIN tbl_societymyprofile s USING(reg_id) WHERE t.reg_id=2 ORDER BY s.date_of_adder DESC LIMIT 1;
Here's a fiddle. See Query #3.

MYSQL joining three tables

I have a simple multiple school management system and I am trying to get total number of teachers, and total number of students for a specific school. My table structures are as follows:
teachers
--------------------------
id | schoolid | Name | etc...
--------------------------
1 | 1 | Bob |
2 | 1 | Sarah|
3 | 2 | John |
students
--------------------------
id | schoolid | Name | etc...
--------------------------
1 | 1 | Jack |
2 | 1 | David|
3 | 2 | Adam |
schools
--------------------------
id | Name | etc...
---------------------------
1 | River Park High |
2 | Stirling High |
I can count just all teachers with the following query:
SELECT COUNT(a.id) AS `totalteachers`
FROM teachers a
LEFT JOIN schools b ON a.schoolid = b.id WHERE b.id = '1'
and similarly I can count the number of teachers with the following query:
SELECT COUNT(a.id) AS `totalstudents`
FROM students a
LEFT JOIN schools b ON a.schoolid = b.id WHERE b.id = '1'
I am however struggling with trying to combine these two queries to get a simple result like this:
totalstudents | totalteachers
--------------------------------
2 | 2
I have tried the following:
SELECT COUNT(a.id) as `totalteachers`, COUNT(c.id) as `totalstudents`
FROM teachers a
LEFT JOIN schools b ON a.schoolid = b.id
LEFT JOIN students c ON c.schoolid=b.id WHERE b.id = '5'
You can do something like this
SELECT
id, name, s.total AS totalstudents, t.total AS totalteachers
FROM schools
JOIN (SELECT schoolid, COUNT(id) AS total FROM teachers GROUP BY schoolid)
AS t ON t.schoolid = id
JOIN (SELECT schoolid, COUNT(id) AS total FROM students GROUP BY schoolid)
AS s ON s.schoolid = id
then you can add where id = 2 or whatever to limit the school.
The problem with the multiple left joins is it generates additional records for each teacher to each student; artifically inflating your counts
There's four ways to solve this: (best imo is what Andrew bone did)
Simply select inline without the joins so the counts are not inflated. (most desirable in my mind as it's easy to maintain)
SELECT (SELECT COUNT(a.id) AS `totalteachers`
FROM teachers a
WHERE A.SchoolID = '1') as TotalTeachers
, (SELECT COUNT(a.id) AS `totalstudents`
FROM students a
WHERE a.SchoolID = '1') as TotalStudents
Use subqueries to get the counts first before the joins, then join. Since count will always be 1 a cross join works.
SELECT totalTeachers, totalStudents
FROM (SELECT COUNT(a.id) AS `totalteachers`
FROM teachers a
LEFT JOIN schools b
ON a.schoolid = b.id
WHERE b.id = '1')
CROSS JOIN (SELECT COUNT(a.id) AS `totalstudents`
FROM students a
LEFT JOIN schools b ON a.schoolid = b.id
WHERE b.id = '1')
Use key word distinct within the count so as not to replicate the counts and negate the artificial inflation (least desirable in my mind as this hides the artifical count increase)
SELECT COUNT(distinct a.id) as `totalteachers`, COUNT(distinct c.id) as `totalstudents`
FROM teachers a
LEFT JOIN schools b ON a.schoolid = b.id
LEFT JOIN students c ON c.schoolid=b.id WHERE b.id = '5'
Another way would be to use a window functions, however these are not available in mySQL.
SELECT COUNT(t.id) AS TotalTeachers, COUNT(st.id) AS TotalStudents
FROM schools s
INNER JOIN teachers t
ON s.id = t.schoolid
INNER JOIN students st
ON s.id = st.schoolid
Try this SQL. I havn't try it but it should work.

mysql count number of votes in votes table

I have 3 tables named election_cand, candidate and votes:
election_cand table:
ele_can_id | election_id | candidate_id
candidate table:
id | canname | canadd | canphone | canmail | candes | canphoto
votes table:
voteid | candidateid | voterid | electionid
my tables with data are:
I want the desired result as
I write the mysql query as:
SELECT a.*,b.*,c.*, count(voteid) AS numrows
FROM election_cand a
left join votes b on a.election_id=b.electionid
left join candidate c on a.candidate_id=c.id
where a.election_id='$get_ele_id' group by a.candidate_id
As I see you only need this query:
SELECT
c.*, COUNT(e.ele_can_id) AS numrows
FROM candidate c
Left Join election_cand e on c.id = e.candidate_id
GROUP BY c.id
describe your schema so we can help you more.
Try this code:
SELECT
c.*, COUNT(v.candidateid) FROM candidate c
LEFT JOIN votes v ON c.id = v.candidateid
WHERE c.id IN
( SELECT candidate_id FROM election_cand WHERE election_id = 4 )
GROUP BY v.candidateid

mysql fetch all row based on join query and latest date time

Hello I have two tables:
table1 - eod_stock
company_code | open | high | low | ltp | close | ycp | total_volume | total_value | datetime
table 2 - company
ID | code | name
here company code = code so to get all name and other info i used this code:
but first one gives me error and 2nd one returns only one row, but i need all 200 companies with their associated info.
select
company.code,
company.name,
eod_stock.open,
eod_stock.high,
max(eod_stock.datetime)
from
company
right join company on company.code= eod_stock.company_code;
and
select
eod_stock.company_code,
max(eod_stock.close),
eod_stock.total_volume,
eod_stock.total_trade,
eod_stock.high,
eod_stock.low,
eod_stock.ltp,
max(eod_stock.datetime),
company.name
from
eod_stock
inner join company on (company.code = eod_stock.company_code);
but first one gives me error and 2nd one returns only one row, but i need all 200 companies with their associated info.
The trick here is to start with a list of the max datetime for each company_code, which you can do with this basic query:
SELECT company_code, MAX(datetime) AS maxdatetime
FROM eod_stock
GROUP BY company_code
Join this to a query that gets company code, company name, and end-of-day values, and you should be all set:
SELECT
company.code,
company.name,
eod_stock.open,
eod_stock.high
FROM eod_stock
INNER JOIN company ON company.code = eod_stock.company_code
INNER JOIN (
SELECT company_code, MAX(datetime) AS maxdatetime
FROM eod_stock
GROUP BY company_code) maxdt
ON maxdt.company_code = eod_stock.company_code AND
maxdt.maxdatetime = eod_stock.datetime
Your first error i guess that your have to write :
Table2 right join Table1
instead of company right join company
the 2nd one to get all company your full join !!
select
eod_stock.company_code,
max(eod_stock.close),
eod_stock.total_volume,
eod_stock.total_trade,
eod_stock.high,
eod_stock.low,
eod_stock.ltp,
max(eod_stock.datetime),
company.name
from
eod_stock
inner join company on (company.code = eod_stock.company_code) group by eod_stock.company_code;
dagfr was correct all i needed to add group by in the query.

Tough Mysql Query

I got a skill test for a quick mysql query. I am given the tables:
Orders OrderItems
----------------------------------------
id id
date order_id(Orders.id)
shipping_amount product_id
order_status price
customer_id quantity
I need to show Orders id and totals (including shipping amount) and records prior to June 1, 2003.
output should be...
| OrderID | OrderTotal |
+-----------+------------+
| 13230 | $55.00 |
| 54455 | $40.00 |
| 59694 | $33.04 |
| 39495 | $21.05 |
The hint is to use Group by or subselect. I have the following statement so far but not sure what to do next.
Select id AS OrderId,***(not sure what to do here)
from Orders join OrderItems on Orders.id=OrderItems.id
I don't have access to a mysql database to test, but I would imagine it looks something like this:
select
o.id OrderID,
(select sum(oi.price * oi.quantity) from order_items oi where oi.order_id = o.id) + o.shipping_amount OrderTotal
from
orders o
where
o.date < str_to_date('2003-06-01', '%Y-%m-%d');
I'd say it must look like this:
SELECT O.ID as OrderID, SUM(OI.price * OI.quantity) AS OrderTotal
FROM Orders O
INNER JOIN OrderItems OI ON O.id = OI.order_Id
WHERE date < '2003-06-01'
GROUP BY O.id
ORDER BY SUM(price * quantity) DESC
Not sure how to format dates in MySQL though or if you can order by an agregate function in this version but I'm pretty sure this is a good start.

Categories