How to rewrite this without duplication, using Standard SQL BIG Query syntax? - sql

Merging two tables the time entries table onto the user's table. Currently using Big query standard SQL. The column id is supposed to have 1 unique id for each entry but yet it pulls multiple of the same id # My Question how to rewrite this query without receiving duplications in the results? How to use LEFT Join with UNION ALL or UNION DISTINCT?
--*** Gives Duplications for some reason ***
SELECT outer_e.hours, outer_e.id, outer_e.updated_at, outer_e.spent_date, u.first_name, u.is_active, u.id AS user_id, u.weekly_capacity FROM
(SELECT e.id, MAX(e.updated_at) AS updated_at FROM `harvest-experiment.harvest.time_entries` AS e
GROUP BY e.id LIMIT 1000) AS inner_e
LEFT JOIN `harvest-experiment.harvest.time_entries` AS outer_e
ON inner_e.id = outer_e.id AND inner_e.updated_at = outer_e.updated_at
LEFT JOIN `harvest-experiment.harvest.users` AS u
ON outer_e.user_id = u.id

I was missing the DISTANT Keyword next my SELECT keyword, by doing so seems to fix the duplication problem in the views.
__***** Current Solution *****———
--*** Returns a Left Joined Table of `time entries` and `users` ***
SELECT DISTINCT outer_e.hours, outer_e.id, outer_e.updated_at, outer_e.spent_date, outer_e.created_at, outer_e.client_id, u.is_admin, u.first_name, u.is_active, u.id AS user_id, u.weekly_capacity, client.name FROM
(SELECT e.id, MAX(e.updated_at) AS updated_at FROM `harvest-experiment.harvest.time_entries` AS e
GROUP BY e.id LIMIT 1000) AS inner_e
LEFT JOIN `harvest-experiment.harvest.time_entries` AS outer_e
ON inner_e.id = outer_e.id AND inner_e.updated_at = outer_e.updated_at
LEFT JOIN `harvest-experiment.harvest.users` AS u
ON outer_e.user_id = u.id

Related

Joining 3 tables in SQL Server

I have three tables namely: user, special_order, corp_order.
I want a result where it can display all orders placed by a user in both order tables.
My SQL statement is:
SELECT
u.user_id,
c.user_id,
s.user_id
FROM
corp_user u
JOIN
special_order s ON s.user_id = u.user_id
JOIN
corp_orders c ON c.user_id = u.user_id;
which is returning unnecessary data.
What you want is all orders, regardless of whether they are special orders or coprporate orders. Decide what columns you want from each corp_user table, and matching columns for orders from each order table and then do two separate queries that are linked by UNION ALL. (You want UNION ALL, not UNION because otherwise if there are exact matches in all fields, the duplicates would be eliminated.
Example for illustration:
SELECT
u.user_id,
s.order_id
FROM
corp_user u
INNER JOIN special_order s on u.user_id = s.user_id
UNION ALL
SELECT
u.user_id,
c.order_id
FROM
corp_user u
INNER JOIN corp_order c on u.user_id = c.user_id
Note: fields must match exactly - not necessarily in names, but in position. Names from first query will be used.

sql - How to have multiple select/from statements in one query

I'm trying to pull a report where each column is selecting from a specific table set. However, one of the columns needs to pull from a completely different table set and still be included in the same report. Of course, this doesn't work:
select u.first_name, ticket_work.time_spent
FROM tickets LEFT OUTER JOIN ticket_work ON ticket_work.ticket_id = tickets.id JOIN users u
(select count(tickets.id) FROM tickets JOIN users u)
where tickets.assigned_to = u.id
...
So just the part (select count(tickets.id) FROM tickets JOIN users u) needs to be selecting from the different table set but still be included in the report.
I'm a little confused by your question. Are you wanting to return the user, the count of tickets for that user, and the amount of time spent overall? If so, something like this should work:
select u.id, u.first_name,
SUM(tw.time_spent) summed_time_spent,
COUNT(DISTINCT t.id) count_tickets
FROM users u
LEFT JOIN tickets t
ON u.id = t.assigned_to
LEFT JOIN ticket_work tw
ON tw.ticket_id = t.id
GROUP BY u.id, u.first_name
Your questions is unclear, but just generally, it sounds like you're trying to join to a derived table (i.e., a query). In that case, do this:
SELECT...
FROM...
table_A A LEFT JOIN
(SELECT keyfield, valuefield FROM table_b WHERE ...) B
ON A.keyfield = B.keyfield
Does that make sense? To make a derived table, you put a query inside of parenthesis, give it an alias ('B' in this case), and then join it to your other tables as though it were a regular table.
Don't know about your table structure but you may use a sub query for such requirement
select u.first_name, ticket_work.time_spent,(select count(tickets.id) FROM tickets where ticket.id=ticket_work.ticket_id) as myCount
FROM tickets LEFT OUTER JOIN ticket_work ON ticket_work.ticket_id = tickets.id JOIN users u
where tickets.assigned_to = u.id

Left outer join and group by issue

I wrote a query. this query sum fields from 2 different table. And grouped by main table id field. But second left outer join is not grouped and giving me different results.
SELECT s.*,
f.firma_adi,
sum(sd.fiyat) AS konak,
sum(ss.fiyat) AS sponsor
FROM fuar_sozlesme1 s
INNER JOIN fuar_firma_2012 f
ON ( s.cari = f.cari )
LEFT OUTER JOIN fuar_sozlesme1_detay sd
ON ( sd.sozlesme_id = s.id )
LEFT OUTER JOIN fuar_sozlesme1_sponsor ss
ON ( ss.sozlesme_id = s.id )
GROUP BY s.id
ORDER BY s.id DESC
I know, it is really complicated but I'm stucking on this issue.
My question is: why second left outer join is not correctly sum of field . If I remove second left outer join or first, everything is normal.
The problem is that you have multiple dimensions on your data, and the number of rows is multiplying beyond what you expect. I would suggest that you run the query for one id, without the group by, to see what rows the join is producing.
One way to fix this is by using correlated subqueries:
select s.*, f.firma_adi,
(select SUM(sd.fiyat)
from fuar_sozlesme1_detay fd
where sd.sozlesme_id = s.id
) as konak,
(select SUM(ss.fiyat)
from fuar_sozlesme1_sponsor ss
where (ss.sozlesme_id = s.id)
) as sponsor
from fuar_sozlesme1 s inner join
fuar_firma_2012 f
on (s.cari = f.cari)
order by s.id DESC
By the way, you appear to by using MySQL (because your query is not parsable in any other dialect). You should tag your questions with the version of the database you are using.

i want to modify this SQL statement to return only distinct rows of a column

select
picks.`fbid`,
picks.`time`,
categories.`name` as cname,
options.`name` as oname,
users.`name`
from
picks
left join categories
on (categories.`id` = picks.`cid`)
left join options
on (options.`id` = picks.oid)
left join users
on (users.fbid = picks.`fbid`)
order by
time desc
that query returns a result that like:
my question is.... I would like to modify the query to select only DISTINCT fbid's. (perhaps the first row only sorted by time)
can someone help with this?
select
p2.fbid,
p2.time,
c.`name` as cname,
o.`name` as oname,
u.`name`
from
( select p1.fbid,
min( p1.time ) FirstTimePerID
from picks p1
group by p1.fbid ) as FirstPerID
JOIN Picks p2
on FirstPerID.fbid = p2.fbid
AND FirstPerID.FirstTimePerID = p2.time
LEFT JOIN Categories c
on p2.cid = c.id
LEFT JOIN Options o
on p2.oid = o.id
LEFT JOIN Users u
on p2.fbid = u.fbid
order by
time desc
I don't know why you originally had LEFT JOINs, as it appears that all picks must be associated with a valid category, option and user... I would then remove the left, and change them to INNER joins instead.
The first inner query grabs for each fbid, the FIRST entry time which will result in a single entity for the FBID. From that, it re-joins to the picks table for the same ID and timeslot... then continues for the rest of the category, options, users join criteria of that single entry.
2 options, you could write a group by clause.
Or you could write a nested query joined back to itself to get pertinent info.
Nested aliased table:
SELECT
n.fBids
FROM
MyTable t
INNER JOIN
(SELECT DISTINCT fBids
FROM MyTable) n
ON n.ID = t.ID
Or group by option
SELECT fBId from MyTable
GROUP BY fBID
select picks.`fbid`, picks.`time`, categories.`name` as cname,
options.`name` as oname, users.`name` from picks left join categories
on (categories.`id` = picks.`cid`) left join options on (options.`id` = picks.oid)
left join users on (users.fbid = picks.`fbid`)
order by time desc GROUP BY picks.`fbid`
select
picks.fbid,
MIN(picks.time) as first_time,
MAX(picks.time) as last_time
from
picks
group by
picks.fbid
order by
MIN(picks.time) desc
However, if you want only distinct fbid's you cannot display cname and other columns at the same time.

Most efficient way to do a conditional mysql join on multiple tables? (Yii php framework)

I have five tables:
tab_template
template_group
group
user_group
user
Tab_template's are organized into groups with the template_group relational table.
Users's are organized into groups with the user_group relational table.
Group's can be public or private (using a tinyint boolean column in the table).
I want to query for all of the tab_templates that are either:
In the same group as the user
Or in a Public group
Here is my current query:
SELECT * FROM tab_template t
LEFT JOIN template_group
ON template_group.tab_template_id=t.id
LEFT JOIN group
ON template_group.tab_template_id=group.id
LEFT JOIN user_group
ON TRUE
WHERE
group.private=0
OR
(template_group.group_id=user_group.group_id
AND
user_group.user_id=2)
GROUP BY t.id;
It works, and it's not SUPER slow per se, but it's hacky the way I join in the user_group table.
The problem is that I need to JOIN the user_group table for a conditional check, but I only need to do that conditional check IF the group is not private.
I know that instead of the third LEFT JOIN with the ON TRUE condition I could add another table to the FROM clause (FROM tab_template t, user_group ug)... but I can't do that because the way Yii's ActiveRecord class works with the DcCriteria I can't modify that part of the statement. I can edit just about any other part of the query but not the FROM clause. Check out the API here: http://www.yiiframework.com/doc/api/CDbCriteria So that's why I am JOINing the user_group table the way I am. Some Yii experts might be able to help me solve that problem, but I'm not sure my query will be faster by FROMing the tables instead of the JOINing them anyway.
Any help would be greatly appreciated! Thanks
My recommendation for situations like these is to use a UNION:
SELECT t.*
FROM TAB_TEMPLATE t
JOIN TEMPLATE_GROUP tg ON tg.tab_template_id = t.id
JOIN GROUP g ON g.id = tg.tab_template_id
AND g.private = 0
UNION
SELECT t.*
FROM TAB_TEMPLATE t
JOIN TEMPLATE_GROUP tg ON tg.tab_template_id = t.id
JOIN GROUP g ON g.id = tg.tab_template_id
AND g.private != 0
JOIN USER_GROUP ug ON ug.group_id = g.id
Way easier to read, which makes it easier to maintain.
I don't have mySql on this machine, so I can't test this:
SELECT
TT.col1,
TT.col2,
...
FROM
Tab_Templates TT
WHERE
EXISTS
(
SELECT *
FROM
Template_Groups TG
WHERE
TG.tab_template_id = TT.id AND
TG.private = 0
) OR
EXISTS
(
SELECT *
FROM
User_Groups UG
INNER JOIN Template_Groups TG2 ON
TG2.tab_template_id = TT.id AND
TG2.group_id = UG.group_id
WHERE
UG.user_id = 2
)