Skip to content
Advertisement

How do I display my query results as part of a string?

My database is for a school project and handles various jobs/contracts which are ran by consultants. Apologies if the context is vague, we haven’t really been given much either.

My current code does what it is suppose to, it selects the forename and surname of the consultant which has led the most contracts/jobs. However I need to display the result in a specific format.

SELECT DISTINCT CONSULTANT_FNAME, CONSULTANT_SNAME
FROM CONSULTANT LEFT JOIN CONTRACT ON CONSULTANT_ID = CONTRACT_LEAD
WHERE CONTRACT_LEAD IN(
SELECT CONTRACT_LEAD
FROM CONTRACT
GROUP BY CONTRACT_LEAD
ORDER BY COUNT(CONTRACT_LEAD) DESC
FETCH NEXT 1 ROWS ONLY);

Currently the result I am getting is:

CONSULTANT_FNAME     CONSULTANT_SNAME
-------------------- --------------------
Cloud                Strife

However I need to display the result as “The consultant who has led the most contracts is: Cloud Strife”.

Advertisement

Answer

You shouldn’t need DISTINCT – you only put it in there because the LEFT JOIN is causing the consultant rows to repeat (multiple contracts per one consultant) but you don’t need the left join either

SELECT 
  'The consultant who has led the most contracts is: ' || CONSULTANT_FNAME || ' ' || CONSULTANT_SNAME
FROM CONSULTANT 
WHERE CONSULTANT_ID IN(
  SELECT CONTRACT_LEAD
  FROM CONTRACT
  GROUP BY CONTRACT_LEAD
  ORDER BY COUNT(CONTRACT_LEAD) DESC
  FETCH NEXT 1 ROWS ONLY
)

The subquery inside the IN returns the most active contract lead id, but this is the same thing as the consultant id – you don’t need to join.

I believe you could also do this:

SELECT 
  'The consultant who has led the most contracts is: ' || CONSULTANT_FNAME || ' ' || CONSULTANT_SNAME
FROM 
  CONSULTANT 
  INNER JOIN CONTRACT ON CONSULTANT_ID = CONTRACT_LEAD
GROUP BY CONSULTANT_FNAME, CONSULTANT_SNAME
ORDER BY COUNT(*) DESC
FETCH NEXT 1 ROWS ONLY

The reason why this works is that grouping on name is effectively the same as grouping on id : it gives a count of how many times the contract table has caused a repeat. There is a slight bug risk with this though that if there really were two different people of identical names they would have their contracts added together. To counter this you can add consultant_id to the group by – if you’re doing a group by then you cannot use columns in the SELECT area that are not mentioned in the group by (unless you put them inside an aggregate function like min, max etc)but you ARE allowed to put columns in the group by that you then don’t use in the select. By adding the ID We provide a way to tell two identically names consultants from having their scores added together:

SELECT 
  'The consultant who has led the most contracts is: ' || s.CONSULTANT_FNAME || ' ' || s.CONSULTANT_SNAME
FROM 
  CONSULTANT s
  INNER JOIN CONTRACT t ON s.CONSULTANT_ID = t.CONTRACT_LEAD
GROUP BY s.CONSULTANT_FNAME, s.CONSULTANT_SNAME, s.CONSULTANT_ID
ORDER BY COUNT(*) DESC
FETCH NEXT 1 ROWS ONLY

The final learning point here; always alias your tables (I used s and t) and use the aliases. This prevents your queries from stopping working if someone adds a new column to eg contracts also called CONSULTANT_FNAME – without the alias your query will only work if column names are unambiguous, and db schema do change over time

Adding table aliases also lets you join one table in twice, which can be vital if e.g. a consultant has a home_address_id and also a work_address_id that map to two different rows in the addresses table. If you joined addresses in only once using home_address_id = address.id OR work_address_id = address.id you’d end up with two rows when the data would be more usable as one row. Here ends sql 101 🙂 but if you have more questions about this nugget of info see something like When to use SQL Table Alias

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement