MySQL, two columns sharing the same join - mysql

SELECT
COALESCE (reports_straddons.employeeid, ldap_karen.uid) as uid,
COALESCE (reports_straddons.thomslocationcountrydescr, ldap_karen.thomslocationcountrydescr, 'NOVALUE') as thomslocationcountrydescr,
COALESCE (reports_straddons.thomslocationcity, ldap_karen.thomslocationcity, 'NOVALUE') as thomslocationcity,
COALESCE (reports_straddons.regionname, ldap_karen.regionname) as regionname,
CONCAT(reports_jobroles.groupabrev, COALESCE(CONCAT(' - ', reports_straddons.sup_role),'')) as sa_title,
ldap_karen.created
FROM
reports_straddons
LEFT JOIN ldap_karen ON reports_straddons.employeeid = ldap_karen.uid
LEFT JOIN reports_jobroles ON reports_straddons.roleid = reports_jobroles.nameid
Right now I am getting the user ID, country, city, region, but the group (compounded roles of roleid - sup_role) is a bit jacked up. The group is a compound name that is made up of:
roleid
sup_role
We have one job role table that we are linking to with names like Manager, Engineer, Sales, AM, PM, whatever.
So an example would be PM - Engineer. The roleid part I got working fine but not understanding what I have done wrong with the second part (and I have tried like 10 things which range from showing up anyone with a sup_role multiple times to only showing those with sup_roles - not everyone has both). So I have a join that is used for two distinct fields and both of those just contain the IDs to the joining table for the same column.
So right now I am getting Engineer - 9, 9 being the ID for the sup_role when it should read Developer if grabbing that name from the table based on the sup_role.
Note: I first logically used LEFT JOIN reports_jobroles ON reports_straddons.sup_role = reports_jobroles.nameid but alas this did not work at all.

I think I understand. The problem is you need to join to a table twice, but you're only joining it once. A simplified version of your problem would look like this:
SELECT
COALESCE (reports_straddons.employeeid, ldap_karen.uid) as uid,
CONCAT(reports_jobroles.groupabrev, COALESCE(CONCAT(' - ', reports_straddons.sup_role),'')) as sa_title
FROM
reports_straddons
LEFT JOIN reports_jobroles ON reports_straddons.roleid = reports_jobroles.nameid
To fix it, you need to do something like this:
SELECT
COALESCE (reports_straddons.employeeid, ldap_karen.uid) as uid,
CONCAT(roles.groupabrev, COALESCE(CONCAT(' - ', suproles.groupabrev),'')) as sa_title
FROM
reports_straddons
LEFT JOIN reports_jobroles roles ON reports_straddons.roleid = roles.nameid
LEFT JOIN reports_jobroles suproles ON reports_straddons.sup_role = suproles.nameid
Notice how I'm joining to reports_jobroles twice, and naming it something different. I'm under the assumption that sup_role will join to the nameid field much like roleid.

Related

SQL Temporary Table or Select

I've got a problem with MySQL select statement.
I have a table with different Department and statuses, there are 4 statuses for every department, but for each month there are not always every single status but I would like to show it in the analytics graph that there is '0'.
I have a problem with select statement that it shows only existing statuses ( of course :D ).
Is it possible to create temporary table with all of the Departments , Statuses and amount of statuses as 0, then update it by values from other select?
Select statement and screen how it looks in perfect situation, and how it looks in bad situation :
SELECT utd.Departament,uts.statusDef as statusoforder,Count(uts.statusDef) as Ilosc_Statusow
FROM ur_tasks_details utd
INNER JOIN ur_tasks_status uts on utd.StatusOfOrder = uts.statusNR
WHERE month = 'Sierpien'
GROUP BY uts.statusDef,utd.Departament
Perfect scenario, now bad scenario :
I've tried with "union" statements but i don't know if there is a possibility to take only "the highest value" for every department.
example :
I've also heard about
With CTE tables, but I don't really get how to use it. Would love to get some tips on it!
Thanks for your help.
Use a cross join to generate the rows you want. Then use a left join and aggregation to bring in the data:
select d.Departament, uts.statusDef as statusoforder,
Count(uts.statusDef) as Ilosc_Statusow
from (select distinct utd.Departament
from ur_tasks_details utd
) d cross join
ur_tasks_status uts left join
ur_tasks_details utd
on utd.Departament = d.Departament and
utd.StatusOfOrder = uts.statusNR and
utd.month = 'Sierpien'
group by uts.statusDef, d.Departament;
The first subquery should be your source of all the departments.
I also suspect that month is in the details table, so that should be part of the on clause.

Sql statement fetching information from two different tables

I have a two tables, one of the table is called participants_tb while the second is called allocation_tb. On the participants_tb, I have my columns as participant_id, name, username.
Under the allocation_tb, I have my columns as allocation_id, sender_username, receiver_username, done. The column done holds any of these three numbers: 0, 1, 2.
I used this sql statement to fetch my values
SELECT *, COUNT(done) d
FROM participants_tb
JOIN allocation_tb ON (username=receiver_username)
WHERE done = 0 || done = 1
GROUP BY receiver_username
It worked very well, the problem I have is that, I want it to also include the information of participants that are in the participants_tb but not in the allocation_tb. I tried to use the left outer join but it did not work as expected because I want it to include participants that are only in the participants_tb but not in the allocation_tb, since the done in the where clause is in the allocation_tb, it won't include those information.
You seem to want:
SELECT p.*, COUNT(a.done) as d
FROM participants_tb p LEFT JOIN
allocation_tb a
ON p.username = a.receiver_username) AND
a.done IN (0, 1)
GROUP BY p.participant_id;
Notes:
The LEFT JOIN keeps all participants.
The GROUP BY needs to be on the first table.
You can use SELECT p.* with the GROUP BY -- assuming that the GROUP BY key is unique (or the primary key).
All columns should be qualified.
IN is an easier way to express your logic.

Using two SELECT statements in SQL?

I have two tables, one is 'points' which contains ID and points. The other table is 'name' and contains ID, Forename, and Surname.
I'm trying to search for the total number of points someone with the forename Anne, and surname Brown, scored.
Would I have to do a join? If so, is this correct?
SELECT Name.Forename, Name.Surname
FROM Name
FULL OUTER JOIN Points
ON Name.ID=Points.ID
ORDER BY Name.Forename;
But then I also have to add the points, so would I have to use:
SELECT SUM (`points`) FROM Points
Then there is also the WHERE statement so that it only searches for the person with this name:
WHERE `Forename`="Anne" OR `Surname`="Brown";
So how does this all come together (based on the assumption that you do something like this)?
SELECT Name.ID, Forename, Surname, SUM(Points)
FROM Name
INNER JOIN Points ON Name.ID = Points.ID
/* Optional WHERE clause:
WHERE Name.ForeName = 'Anne' AND Name.Surname='Brown'
*/
GROUP BY Name.ID, Name.Forename, Name.Surname
So, first, your answer:
select sum(points) as Points
from
Points
inner join Name on Name.ID = Points.ID
where
Name.Forename ='Anne' and Name.SurName='Brown'
Secondly, FULL JOINS are bad since they pull all values from both sets even those without matches. If you want to only return values that match your criteria (A & B) you must use an INNER JOIN.
Thirdly, here is the MySQL reference documentation on SQL statement syntax. Please consider reading up on it and familiarizing yourself at least with the basics like JOINs, aggregation (including GROUP BY and HAVING), WHERE clauses, UNIONs, some of the basic functions provided, and perhaps subqueries. Having a good base in those will get you 99% of the way through most MySQL queries.
You can write it like this with a subquery.
SELECT Name.Forename, Name.Surname, Name.ID,
(SELECT SUM (`points`) FROM Points where Points.ID = Name.ID) as total_points
FROM Name ORDER BY Name.Forename;
However, I would like to point out, that it appears that your linking of the tables is incorrect. I can not be completely sure without seeing the tables, but I imagine it should be where points.userid = name.id

Getting object if count is less then a number

I have 2 simple tables - Firm and Groups. I also have a table FirmGroupsLink for making connections between them (connection is one to many).
Table Firm has attributes - FirmID, FirmName, City
Table Groups has attributes - GroupID, GroupName
Table FirmGroupsLink has attributes - FrmID, GrpID
Now I want to make a query, which will return all those firms, that have less groups then #num, so I write
SELECT FirmID, FirmName, City
FROM (Firm INNER JOIN FirmGroupsLink ON Firm.FirmID =
FirmGroupsLink.FrmID)
HAVING COUNT(FrmID)<#num
But it doesn't run, I try this in Microsoft Access, but it eventually should work for Sybase. Please show me, what I'm doing wrong.
Thank you in advance.
In order to count properly, you need to provide by which group you are couting.
The having clause, and moreover the count can't work if you are not grouping.
Here you are counting by Firm. In fact, because you need to retrieve information about the Firm, you are grouping by FirmId, FirmName and City, so the query should look like this:
SELECT Firm.FirmID, Firm.FirmName, Firm.City
FROM Firm
LEFT OUTER JOIN FirmGroupsLink
ON Firm.FirmID = FirmGroupsLink.FrmID
GROUP BY Firm.FirmID, Firm.FirmName, Firm.City
HAVING COUNT(FrmID) < #num
Note that I replace the INNER JOIN by a LEFT OUTER JOIN, because you might want Firm which doesn't belongs to any groups too.

Missing record in a complex SELECT FULL JOIN statement

I created a SQL statement that should return the number of appointments receive by all salesmen. I work with 3 tables, Contract, Salesmen and Appointment, and I need to show how many appointments was received by each salesmen.
My problem is that although I use a Full Join the result doesn't show people who didn't receive any appointments. I found that there is a problem about constraint.
I took a look to Except, Intercept and Union option but none of those could solve my problem. Which other way could I use to get the full list of reps having or not received some appointments?
There is an example of the statement I used:
SELECT C.RepID, COUNT(A.AppID) AS AppAttrib, C.AppointmentPurchased, S.Name, S.FirstName
FROM Repartition.dbo.Contract C
FULL JOIN Repartition.DBO.Appointment A
ON C.RepID = A.RepID
LEFT JOIN Repartition.DBO.Salesmen S
ON S.RepID = C.RepID
GROUP BY C.RepID, V.Nom, S.Name, S.FirstName
Thanks for your help,
Antenor
Not knowing your table structure in detail, I'm just guessing here - but I think your query starts at the wrong place - you should start with the Salesmen table, and go from there. So basically, select those columns from the Salesmen table that you need, and then join in the other tables as needed.
Something like this:
SELECT
s.RepID, S.Name, S.FirstName,
COUNT(A.AppID) AS AppAttrib,
C.AppointmentPurchased
FROM
Repartition.dbo.Salesmen s
LEFT OUTER JOIN
Repartition.dbo.Contract c ON s.RepID = c.RepID
LEFT OUTER JOIN
Repartition.dbo.Appointment a ON s.RepID = a.RepID
GROUP BY
s.RepID, s.Name, s.FirstName