Mysql Joins- Results are duplicated how to fix it - mysql

I am very new to MySQL and also this is my first question if there is any mistakes please forgive me.
I have 6 tables i want to take report using this 6 tables. One of my report to access all the 6 tables and print the data as per the Query we write.Now the problem is i have write my query but this will return lot of duplicate data.How to avoid that guide me please.
SELECT
#rownum := #rownum + 1 AS RowNumber,
a.vnumber,a.vname,
b.eid,b.name,b.mobile,
c.vid,c.emp_id,c.pick_place,c.start_time,c.drop_place,c.stop_time,
c.pickupkm,c.drops,c.type_of_trip,c.travelkm,c.tamt,c.dates,
d.vid,d.emp_id,d.expcal,d.exp1,d.exp2,d.exp3,
d.exp4,d.exp5,d.expamt,d.expdesc,d.dates,
e.emp_id,e.vid,e.opeing_km,e.opeing_cash,e.closing_km,
e.closing_cash,e.opeing_date,e.opeing_time,e.closing_date,
e.closing_time, f.vid,f.emp_id,
f.totkm,f.totamt,f.expenses,f.handover_amt,
f.balance_amt,f.handover_to,f.plstatus,f.entry_date
from
add_vehicle a
LEFT JOIN third_table c ON a.vnumber=c.vid
LEFT JOIN add_employees b ON b.eid=c.emp_id
LEFT JOIN fourth_table d ON a.vnumber=d.vid
LEFT JOIN shift e ON b.eid=e.emp_id
LEFT JOIN five_table f ON a.vnumber=f.vid,
(SELECT #rownum := 0) r
WHERE
c.type_of_trip IS NOT NULL AND
c.dates BETWEEN '2017-04-01' AND '2017-04-19' AND
d.dates BETWEEN '2017-04-01' AND '2017-04-19' AND
f.entry_date BETWEEN '2017-04-01' AND '2017-04-19' AND
c.vid='STAT01' AND f.vid='STAT01' AND c.emp_id='1' AND
f.emp_id='1' AND e.emp_id='1'
ORDER BY c.dates,f.entry_date DESC
sorry for SQL fiddle not working.
This is my Tables and sample data.
My sample data

Maybe you could use "group by" by the column you wish to be unique, or use "distinct"

you can use GROUP BY function for avoiding duplicate data. Just use group by for those data whome you want to be unique. Example like below
GROUP BY eid
Add this query at the end so you can avoid same employee.
Also you can use INNER JOIN

Related

MySQL Inner join naming error?

http://sqlfiddle.com/#!9/e6effb/1
I'm trying to get a top 10 by revenue per brand for France on december.
There are 2 tables (first table has date, second table has brand and I'm trying to join them)
I get this error "FUNCTION db_9_d870e5.SUM does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual"
Is my use of Inner join there correct?
It's because you had an extra space after SUM. Please change it from
SUM (o1.total_net_revenue)to SUM(o1.total_net_revenue).
See more about it here.
Also after correcting it, your query still had more error as you were not selecting order_id on your intermediate table i2 so edited here as :
SELECT o1.order_id, o1.country, i2.brand,
SUM(o1.total_net_revenue)
FROM orders o1
INNER JOIN (
SELECT i1.brand, SUM(i1.net_revenue) AS total_net_revenue,order_id
FROM ordered_items i1
WHERE i1.country = 'France'
GROUP BY i1.brand
) i2
ON o1.order_id = i2.order_id AND o1.total_net_revenue = i2.total_net_revenue
AND o1.total_net_revenue = i2.total_net_revenue
WHERE o1.country = 'France' AND o1.created_at BETWEEN '2016-12-01' AND '2016-12-31'
GROUP BY 1,2,3
ORDER BY 4
LIMIT 10`
--EDIT stack Fan is correct that the o2.total_net_revenue exists. My confusion was because the data structure duplicated three columns between the tables, including one that was being looked for.
There were a couple errors with your SQL statement:
1. You were referencing an invalid column in your outer-select-SUM function. I believe you're actually after i2.total_net_revenue.
The table structure is terrible, the "important" columns (country, revenue, order_id) are duplicated between the two tables. I would also expect the revenue columns to share the same name, if they always have the same values in them. In the example, there's no difference between i1.net_revenue and o1.total_net_revenue.
In your inner join, you didn't reference i1.order_id, which meant that your "on" clause couldn't execute correctly.
PROTIP:
When you run into an issue like this, take all the complicated bits out of your query and get the base query working correctly first. THEN add your functions.
PROTIP:
In your GROUP BY clause, reference the actual columns, NOT the column numbers. It makes your query more robust.
This is the query I ended up with:
SELECT o1.order_id, o1.country, i2.brand,
SUM(i2.total_net_revenue) AS total_rev
FROM orders o1
INNER JOIN (
SELECT i1.order_id, i1.brand, SUM(i1.net_revenue) AS total_net_revenue
FROM ordered_items i1
WHERE i1.country = 'France'
GROUP BY i1.brand
) i2
ON o1.order_id = i2.order_id AND o1.total_net_revenue = i2.total_net_revenue
AND o1.total_net_revenue = i2.total_net_revenue
WHERE o1.country = 'France' AND o1.created_at BETWEEN '2016-12-01' AND '2016-12-31'
GROUP BY o1.order_id, o1.country, i2.brand
ORDER BY total_rev
LIMIT 10

Syntax on update with multiple joins

I'm having an issue updating a table with a select using multiple joins. I feel like everything is in place but I'm getting some syntax problems around the end, as commented below.
UPDATE ambition.ambition_totals a
INNER JOIN (SELECT
c.user AS UserID,
COUNT(*) AS dealers,
ROUND((al.NumberOfDealers / al.NumberOfDealerContacts) * 100 ,2) AS percent
FROM contact_events c
JOIN users u
ON c.user = u.id
JOIN dealers d
ON c.dealer_num = d.dealer_num
LEFT JOIN (
SELECT user_id, COUNT(*) AS NumberOfDealerContacts,
SUM(CASE WHEN ( d.next_call_date + INTERVAL 7 DAY) THEN 1 ELSE 0 END) AS NumberOfDealers
FROM attr_list AS al
JOIN dealers AS d ON d.csr = al.data
WHERE al.attr_id = 14
GROUP BY user_id)) as al
ON al.user_id = a.ext_id -- this is where I have a syntax error
SET a.dealers_contacted = al.dealers,
a.percent_up_to_date = al.percent;
As shown, I'm getting the data needed from these joins but I'm unable to update based on my ON clause in the final join. The select itself works apart from this, but I'm just trying to alter it to update a table.
I'm sure I'm just overlooking something in the syntax but I get an error that 'every derived table must have its own alias'.
UPDATE
Original working select that needs to be converted into the update:
SELECT
c.user AS UserID,
COUNT(*) AS Number_of_recorded_events,
ROUND((al.NumberOfDealers / al.NumberOfDealerContacts) * 100 ,2) AS Percentage_up_to_date
FROM contact_events c
JOIN users u
ON c.user = u.id
JOIN dealers d
ON c.dealer_num = d.dealer_num
LEFT JOIN (
SELECT user_id, COUNT(*) AS NumberOfDealerContacts,
SUM(CASE WHEN ( d.next_call_date + INTERVAL 7 DAY) THEN 1 ELSE 0 END) AS NumberOfDealers
FROM jackson_id.attr_list AS al
JOIN jfi_dealers.dealers AS d ON d.csr = al.data
WHERE al.attr_id = 14
GROUP BY user_id) AS al
ON al.user_id = c.user
GROUP BY UserID;
'every derived table must have its own alias'
This error is pretty clear. A derived table is when you put a subquery in a FROM clause or JOIN clause, which you do twice in your query.
Every time you do this, you must give each of these derived table subqueries an alias, so you can reference columns returned by the subquery.
Like:
SELECT t.foo FROM (SELECT foo FROM MyTable) AS t
This must be done for every such subquery. In your case, you have something like this form:
UPDATE a
INNER JOIN (
SELECT ... FROM c JOIN u JOIN d
LEFT JOIN (SELECT ... FROM al JOIN d ...)
) AS al
SET ...
You have one level of subquery, which you give the alias al.
But you don't give an alias for the innermost subquery, the one you did a LEFT JOIN on. That one needs an alias too.
P.S.: This question is actually a duplicate of What is the error "Every derived table must have its own alias" in MySQL? from 2009. I know Stack Overflow encourages us to close new questions as duplicates if there is already an old answer. But I also know the reality is that people tend not to search old posts much.
On the other hand, that old Stack Overflow post from 2009 is literally the first result when I google for the error string 'every derived table must have its own alias'.

Remove duplicates of ONE table in a multiple JOIN result in My SQL

I am trying to display some info merging 4 tables. My tables are device, device_model, sub_product_area and borrow_device.
The problem I have is, when I link the tables to device table using a LEFT JOIN there are some duplicates for the transaction_ID from the borrow_device table. So I want to ORDER BY on transaction_Mode ONLY for that LEFT JOIN and only take the 'red' color relevant transaction_ID at such instances. I have tried SELECT DISTINCT but it didn't work. None of the similar question answers worked.
Here is my query ->
SELECT *
FROM device b
LEFT OUTER JOIN device_model a ON (b.`model_ID`=a.`model_ID`)
LEFT JOIN sub_product_area c ON (b.`sub_Product_Area_ID` = c.`sub_Product_Area_ID`)
LEFT JOIN borrow_device d ON (d.`device_ID` = b.`device_ID` and CURDATE() between from_Date and to_Date)
ORDER BY d.transaction_Mode DESC
My table structures are as below -:
Thanks in advance!
Adding a 'GROUP BY' to the end solved my problem. Thanks everyone!
device table and sub_product_area table have 2 field related are sub_product_area_id and product_area_id. in your SQl statement try to add "and b.product_Area_ID = c.product_Area_ID", so your syntax would be like this bellow :
SELECT *
FROM device b
LEFT OUTER JOIN device_model a ON (b.`model_ID`=a.`model_ID`)
LEFT JOIN sub_product_area c ON (b.`sub_Product_Area_ID` = c.`sub_Product_Area_ID` and b.`product_Area_ID` = c.`product_Area_ID`)
LEFT JOIN borrow_device d ON (d.`device_ID` = b.`device_ID` and CURDATE() between from_Date and to_Date)
ORDER BY d.transaction_Mode DESC

Grouping method

I am working on a query with the following format:
I require all the columns from the Database 'A', while I only require the summed amount (sum(amount)) from the Database 'B'.
SELECT A.*, sum(B.CURTRXAM) as 'Current Transaction Amt'
FROM A
LEFT JOIN C
ON A.Schedule_Number = C.Schedule_Number
LEFT JOIN B
ON A.DOCNUMBR = B.DOCNUMBR
ON A.CUSTNMBR = B.CUSTNMBR
GROUP BY A
ORDER BY A.CUSTNMBR
My question is regarding the grouping statement, database A has about 12 columns and to group by each individually is tedious, is there a cleaner way to do this such as:
GROUP BY A
I am not sure if a simpler way exists as I am new to SQL, I have previously investigated GROUPING_ID statements but thats about it.
Any help on lumped methods of grouping would be helpful
Since the docnumber is the primary key - just use the following SQL:
SELECT A.*, sum(B.CURTRXAM) as 'Current Transaction Amt'
FROM A
LEFT JOIN C
ON A.Schedule_Number = C.Schedule_Number
LEFT JOIN B
ON A.DOCNUMBR = B.DOCNUMBR
ORDER BY RM20401.CUSTNMBR
GROUP BY A.DOCNUMBR

How to convert code written in INNER JOIN to Subquery

Need some help with converting code from Join statement into Subquery.
I need to remove GROUP BY from it somehow, when converted into Subquery and don't know how.
Managed to put small portion of subquery at the end of the code, don't know how to do rest.
Need some help, thank you.
Here is the sample of the code: (need to convert into SQL Server syntax)
SELECT
b.Number, t.IDTyre, SUM(c.Price)
FROM Tyre AS t
INNER JOIN Bill AS b ON t.BillID = b.IDBill
INNER JOIN Customer AS c ON c.TyreID = t.IDTyre
GROUP BY b.Number, t.IDTyre
HAVING SUM(c.Price) < 3000 OR t.IDTyre NOT IN (SELECT c.TyreID FROM Customer AS c)
Check if the below query works:
SELECT
(Select b.Number From Bill AS b Where b.IDBill = t.BillID) as Number,
t.IDTyre as TyreID,
(Select SUM(c.Price) From Customer AS c Having SUM(c.Price) < 3000 OR t.IDTyre NOT IN (SELECT Distinct c.TyreID FROM Customer AS c) And c.TyreID = t.IDTyre) as Price
FROM Tyre AS t
Why are you trying to convert this to Sub Query?
JOINS are the best options while dealing with linking tables.
Also the "NOT IN" that you are trying to do at the end is also not good, you should use "NOT EXISTS". Change this to: OR NOT EXISTS (SELECT * FROM Customer AS c WHERE t.IDTyre=c.TyreID)