SQL statement that returns sums of records and returns both make names in SQL Server - sql

I'm a big confused on this one. I'm trying to use a SQL statement that sums up two different records but displays both 'Makes' of each row. I currently have this statement..
SELECT
tDealerships.CapShortName,
SUM(tObjective.CommitObj) AS CommitObj,
SUM(tObjective.ActualMTD) AS MTD,
SUM(tObjective.DelToday) AS DelT,
SUM(tObjective.ActualMTD)/Sum(tObjective.CommitObj) AS CommitUnit,
SUM(tObjective.CommitGrossObj) AS CommitGrossObj,
SUM(tObjective.GrossActual) AS GrossActual,
SUM(tObjective.GrossActual)/Sum(tObjective.CommitGrossObj) as CommitGross,
Sum(tObjective.ActualMTD)/Sum(tObjective.GrossActual) AS MTDPRU
FROM
tObjective, tMake, tDealerships
WHERE
tObjective.DealershipID = 10
AND NewUsed = 'New'
AND tObjective.MakeID = tMake.MakeID
AND tObjective.DealershipID = tDealerships.DealershipID
AND (tMake.Make LIKE '%BUICK%' OR tMake.Make LIKE '%GMC%')
GROUP BY
tDealerships.CapShortName
which returns this..
However, I need to display the two makes that it is summing up which is Buick and GMC.
If I add the make in the statement, I must group by the make which then separates them into two row sums.. one for Buick and then one for GMC. Is there a better way or doing this? I am able to make it do what I need it to do? I have been stuck on this one for a bit now. Any suggestions/help is greatly appreciated!
EDIT: The ideal result is having 1 result with an additional column named Make that displays both Buick/GMC together.

You had to hard-code the makes for the LIKE strings. Why not just hard code them in a literal for the make column?
SELECT
tDealerships.CapShortName,
SUM(tObjective.CommitObj) AS CommitObj,
SUM(tObjective.ActualMTD) AS MTD,
SUM(tObjective.DelToday) AS DelT,
SUM(tObjective.ActualMTD)/Sum(tObjective.CommitObj) AS CommitUnit,
SUM(tObjective.CommitGrossObj) AS CommitGrossObj,
SUM(tObjective.GrossActual) AS GrossActual,
SUM(tObjective.GrossActual)/Sum(tObjective.CommitGrossObj) as CommitGross,
Sum(tObjective.ActualMTD)/Sum(tObjective.GrossActual) AS MTDPRU
------
'GMC/Buick' As Make
------
FROM tObjective, tMake, tDealerships
WHERE tObjective.DealershipID = 10
AND NewUsed = 'New'
AND tObjective.MakeID = tMake.MakeID
AND tObjective.DealershipID = tDealerships.DealershipID
AND (tMake.Make LIKE '%BUICK%'
OR tMake.Make LIKE '%GMC%')
GROUP BY tDealerships.CapShortName

I think that something as simple as grouping on the make as well would solve your problem, if I am reading it correctly?
SELECT
tDealerships.CapShortName,
SUM(tObjective.CommitObj) AS CommitObj,
SUM(tObjective.ActualMTD) AS MTD,
SUM(tObjective.DelToday) AS DelT,
SUM(tObjective.ActualMTD)/Sum(tObjective.CommitObj) AS CommitUnit,
SUM(tObjective.CommitGrossObj) AS CommitGrossObj,
SUM(tObjective.GrossActual) AS GrossActual,
SUM(tObjective.GrossActual)/Sum(tObjective.CommitGrossObj) as CommitGross,
Sum(tObjective.ActualMTD)/Sum(tObjective.GrossActual) AS MTDPRU
FROM tObjective, tMake, tDealerships
WHERE tObjective.DealershipID = 10
AND NewUsed = 'New'
AND tObjective.MakeID = tMake.MakeID
AND tObjective.DealershipID = tDealerships.DealershipID
AND (tMake.Make LIKE '%BUICK%'
OR tMake.Make LIKE '%GMC%')
GROUP BY tMake.Make, tDealerships.CapShortName

Related

multiplie outputs with different wheres

What do I have to change to get different results from different names.The table should give me the debts of each of them, this is calculated by the amount and the price of the drink. Now it should show all the names with the corresponding invoice that happens after the select
%sql select name, sum(getraenk.preis*schulden.menge) schulden from schulden \
join person on (fk_person = person.id)\
join getraenk on (fk_getraenk = getraenk.id)\
where name like ("dani")
Edit: it should spend all the names with their debts, that is:
dani = 8.5
michael = 12.5
...
Just in case your problem is very simple, you should be able to see all names and values with an SQL that looks like this:
select name, getraenk.preis*schulden.menge schulden
from schulden
join person on (fk_person = person.id)
join getraenk on (fk_getraenk = getraenk.id)
Note that I removed the where clause... this was the part that limited it to one name.
You also don't need the sum clause here unless you are doing a group by
Have you considered simply using GROUP BY name at the end of this query?
https://www.w3schools.com/sql/sql_groupby.asp
This will give you the sum of total debt for all names in your table which sounds like the result you are looking for.
You're missing
GROUP BY name
in the query.

Where Multiple Values SQL SERVER

For this code I need the sum of the serv1 - serv8 where the student is receiving "Speech Language Therapy". I can not for the life of me figure out how to get those. If I say where serv1 equals 'SLT' then it will show up as null for serv 2. If I do it for serv2 it will show up as another service like DD for serv1.
My sum isn't working I would like to sum all of the services up by school but I'll take what anyone is willing to help me with. Any help is appreciated
SELECT SPE_Student_Profile_VW.school_code,
SPE_Student_Profile_VW.organization_name AS [[[School Name]]]]]]],
SPE_Student_Profile_VW.sis_number,
SPE_Student_Profile_VW.primary_disability_code,
SPE_Student_Profile_VW.secondary_disability_code,
SPE_Student_Profile_VW.tertiary_disability_code,
SPE_Student_Profile_VW.serv1,
SUM (SPE_Student_Profile_VW.mins1),
SPE_Student_Profile_VW.serv2,
SPE_Student_Profile_VW.mins2,
SPE_Student_Profile_VW.serv3,
SPE_Student_Profile_VW.mins3,
SPE_Student_Profile_VW.serv4,
SPE_Student_Profile_VW.mins4,
SPE_Student_Profile_VW.serv5,
SPE_Student_Profile_VW.mins5,
SPE_Student_Profile_VW.serv6,
SPE_Student_Profile_VW.mins6,
SPE_Student_Profile_VW.serv7,
SPE_Student_Profile_VW.mins7,
SPE_Student_Profile_VW.serv8,
SPE_Student_Profile_VW.mins8
FROM DBO.SPE_Student_Profile_VW SPE_Student_Profile_VW
WHERE ( SPE_Student_Profile_VW.serv1 = 'Speech Language Therapy'
AND SPE_Student_Profile_VW.school_code = '47')
GROUP BY SPE_Student_Profile_VW.school_code,
SPE_Student_Profile_VW.organization_name,
SPE_Student_Profile_VW.sis_number,
SPE_Student_Profile_VW.primary_disability_code,
SPE_Student_Profile_VW.secondary_disability_code,
SPE_Student_Profile_VW.tertiary_disability_code,
SPE_Student_Profile_VW.serv1,
SPE_Student_Profile_VW.mins1,
SPE_Student_Profile_VW.serv2,
SPE_Student_Profile_VW.mins2,
SPE_Student_Profile_VW.serv3,
SPE_Student_Profile_VW.mins3,
SPE_Student_Profile_VW.serv4,
SPE_Student_Profile_VW.mins4,
SPE_Student_Profile_VW.serv5,
SPE_Student_Profile_VW.mins5,
SPE_Student_Profile_VW.serv6,
SPE_Student_Profile_VW.mins6,
SPE_Student_Profile_VW.serv7,
SPE_Student_Profile_VW.mins7,
SPE_Student_Profile_VW.serv8,
SPE_Student_Profile_VW.mins8
the column you are trying to sum should not be in the group by clause, all the others should.
What I mean is the SELECT clause has this:
SUM (SPE_Student_Profile_VW.mins1),
and the GROUP BY has this part which should not be there:
SPE_Student_Profile_VW.mins1,
because it is the column he is trying to sum and you can't group by a column that you are aggregating with a function and that is why SUM isn't working
not sure of what is required but from what I get, you can probably get what you need if you add another
OR
in your
WHERE
Something like
WHERE (SPE_Student_Profile_VW.serv1 = 'Speech Language Therapy'
AND SPE_Student_Profile_VW.school_code = '47') OR
(SPE_Student_Profile_VW.serv2 = 'Speech Language Therapy'
AND SPE_Student_Profile_VW.school_code = '47') OR
SPE_Student_Profile_VW.serv3 = 'Speech Language Therapy'
AND SPE_Student_Profile_VW.school_code = '47'
and so on.
Thanks.
In Group by clause use all columns which you are used in select statement.Except the column you are calculating sum in select statement.
Thanks.

SQL - Getting a column from another table to join this query

I've got the code below which displays the location_id and total number of antisocial crimes but I would like to get the location_name from a different table called location_dim be output as well. I tried to find a way to UNION it but couldn't get it to work. Any ideas?
SELECT fk5_location_id , COUNT(fk3_crime_id) as TOTAL_ANTISOCIAL_CRIMES
from CRIME_FACT
WHERE fk1_time_id = 3 AND fk3_crime_id = 1
GROUP BY fk5_location_id;
You want to use join to lookup the location name. The query would probably look like this:
SELECT ld.location_name, COUNT(cf.fk3_crime_id) as TOTAL_ANTISOCIAL_CRIMES
from CRIME_FACT cf join
LOCATION_DIM ld
on cf.fk5_location_id = ld.location_id
WHERE cf.fk1_time_id = 3 AND cf.fk3_crime_id = 1
GROUP BY ld.location_name;
You need to put in the right column names for ld.location_name and ld.location_id.
you need to find a relationship between the two tables to link a location to crime. that way you could use a "join" and select the fields from each table you are interested in.
I suggest taking a step back and reading up on the fundamentals of relational databases. There are many good books out there which is the perfect place to start.

complex MySQL Order by not working

Here is the select statement I'm using. The problem happens with the sorting. When it is like below, it only sorts by t2.userdb_user_first_name, doesn't matter if I put that first or second. When I remove that, it sorts just fine by the displayorder field value pair. So I know that part is working, but somehow the combination of the two causes the first_name to override it. What I want is for the records to be sorted by displayorder first, and then first_name within that.
SELECT t1.userdb_id
FROM default_en_userdbelements as t1
INNER JOIN default_en_userdb AS t2 ON t1.userdb_id = t2.userdb_id
WHERE t1.userdbelements_field_name = 'newproject'
AND t1.userdbelements_field_value = 'no'
AND t2.userdb_user_first_name!='Default'
ORDER BY
(t1.userdbelements_field_name = 'displayorder' AND t1.userdbelements_field_value),
t2.userdb_user_first_name;
Edit: here is what I want to accomplish. I want to list the users (that are not new projects) from the userdb table, along with the details about the users that is stored in userdbelements. And I want that to be sorted first by userdbelements.displayorder, then by userdb.first_name. I hope that makes sense? Thanks for the really quick help!
Edit: Sorry for disappearing, here is some sample data
userdbelements
userdbelements_id userdbelements_field_name userdbelements_field_value userdb_id
647 heat 1
648 displayorder 1 - Sponsored 1
645 condofees 1
userdb
userdb_id userdb_user_name userdb_emailaddress userdb_user_first_name userdb_user_last_name
10 harbourlights info#harbourlightscondosminium.ca Harbourlights 1237 Northshore Blvd, Burlington
11 harbourview info#harbourviewcondominium.ca Harbourview 415 Locust Street, Burlington
12 thebalmoral info#thebalmoralcondominium.ca The Balmoral 2075 & 2085 Amherst Heights Drive, Burlington
You are trying to use an invalid ORDER BY.
ORDER BY (t1.userdbelements_field_name = 'displayorder' AND t1.userdbelements_field_value)
It must reference a table column or returned aliased column.
I really cannot follow how this query would even be possible as you already have limited
t1.userdbelements_field_name = newproject and then you wish to order by the case of it being equal to displayorder.
Could you please modify your question to state exactly what it is that you are trying to accomplish in your order by clause?
From what I understand, you'd have to join to default_en_userdbelements solely for the displayorder value. However, I suspect there's something wrong with your query and that it probably returns duplicate values for userdb_id.
Perhaps you should say what you're trying to actually do, not explain the way you're trying to do it.
SELECT t1.userdb_id
FROM default_en_userdbelements AS t1
JOIN default_en_userdb AS t2 ON t1.userdb_id = t2.userdb_id
JOIN default_en_userdbelements AS o ON (o.userdb_id, o.userdbelements_field_name)
= (t1.userdb_id, 'displayorder')
WHERE t1.userdbelements_field_name = 'newproject'
AND t1.userdbelements_field_value = 'no'
AND t2.userdb_user_first_name != 'Default'
ORDER BY o.userdbelements_field_value,
t2.userdb_user_first_name
You could do something like this:
ORDER BY
(CASE WHEN t1.userdbelements_field_name = 'displayorder'
THEN t1.userdbelements_field_value
ELSE $some_large_number
END),
t2.userdb_user_first_name;
It sorts using the value of t1.userdbelements_field_value when t1.userdbelements_field_name = 'displayorder', but you have to supply some other value of the same type to apply for the ELSE.

Django annotate() multiple times causes wrong answers

Django has the great new annotate() function for querysets. However I can't get it to work properly for multiple annotations in a single queryset.
For example,
tour_list = Tour.objects.all().annotate( Count('tourcomment') ).annotate( Count('history') )
A tour can contain multiple tourcomment and history entries. I'm trying to get how many comments and history entries exist for this tour. The resulting
history__count and tourcomment__count
values will be incorrect. If there's only one annotate() call the value will be correct.
There seems to be some kind of multiplicative effect coming from the two LEFT OUTER JOINs. For example, if a tour has 3 histories and 3 comments, 9 will be the count value for both. 12 histories + 1 comment = 12 for both values. 1 history + 0 comment = 1 history, 0 comments (this one happens to return the correct values).
The resulting SQL call is:
SELECT `testapp_tour`.`id`, `testapp_tour`.`operator_id`, `testapp_tour`.`name`, `testapp_tour`.`region_id`, `testapp_tour`.`description`, `testapp_tour`.`net_price`, `testapp_tour`.`sales_price`, `testapp_tour`.`enabled`, `testapp_tour`.`num_views`, `testapp_tour`.`create_date`, `testapp_tour`.`modify_date`, `testapp_tour`.`image1`, `testapp_tour`.`image2`, `testapp_tour`.`image3`, `testapp_tour`.`image4`, `testapp_tour`.`notes`, `testapp_tour`.`pickup_time`, `testapp_tour`.`dropoff_time`, COUNT(`testapp_tourcomment`.`id`) AS `tourcomment__count`, COUNT(`testapp_history`.`id`) AS `history__count`
FROM `testapp_tour` LEFT OUTER JOIN `testapp_tourcomment` ON (`testapp_tour`.`id` = `testapp_tourcomment`.`tour_id`) LEFT OUTER JOIN `testapp_history` ON (`testapp_tour`.`id` = `testapp_history`.`tour_id`)
GROUP BY `testapp_tour`.`id`
ORDER BY `testapp_tour`.`name` ASC
I have tried combining the results from two querysets that contain a single call to annotate (), but it doesn't work right... You can't really guarantee that the order will be the same. and it seems overly complicated and messy so I've been looking for something better...
tour_list = Tour.objects.all().filter(operator__user__exact = request.user ).filter(enabled__exact = True).annotate( Count('tourcomment') )
tour_list_historycount = Tour.objects.all().filter( enabled__exact = True ).annotate( Count('history') )
for i,o in enumerate(tour_list):
o.history__count = tour_list_historycount[i].history__count
Thanks for any help. Stackoverflow has saved my butt in the past with a lot of already-answered questions, but I wasn't able to find an answer to this one yet.
Thanks for your comment. That didn't quite work but it steered me in the right direction. I was finally able to solve this by adding distinct to both Count() calls:
Count('tourcomment', distinct=True)
tour_list = Tour.objects.all().annotate(tour_count=Count('tourcomment',distinct=True) ).annotate(history_count=Count('history',distinct=True) )
You have to add distinct=True to get the proper result else it will return the wrong answer.
I can't guarantee that this will solve your problem, but try appending .order_by() to your call. That is:
tour_list = Tour.objects.all().annotate(Count('tourcomment')).annotate(Count('history')).order_by()
The reason for this is that django needs to select all the fields in the ORDER BY clause, which causes otherwise identical results to be selected. By appending .order_by(), you're removing the ORDER BY clause altogether, which prevents this from happening. See the aggregation documentation for more information on this issue.