SQL ORDER BY 0 (int) needs to be first - sql

I am attempting to sort an integer field in ASC order, but it is automatically putting the "0" value near the bottom (just above NULL values).
I am using SQL Server 2005. I think my DBMS is outdated, because I attempted to use NULLS FIRST, and it was not recognized.
*Edited to show better query (thanks for the quick feedback)
What I want to see:
PriSortOrder/CommunityName
0/Towson
1/Atlanta
2/Baltimore
NULL
What I see:
PriSortOrder/CommunityName
1/Atlanta
2/Baltimore
0/Towson
NULL
Query:
SELECT PriSortOrder, CommunityName
FROM Communities
WHERE InCatalog=1
ORDER BY PriSortOrder

Until you show the PrioritySortOrder value as well as the Community value, you can't say that the data is in the right (or wrong) order. For example, if the data is:
Community PrioritySortOrder
0 5
1 0
2 3
NULL 6
You will get the output:
1
2
0
NULL
If the data is:
Community PrioritySortOrder
0 0
1 1
2 2
NULL 3
then you will get the result:
0
1
2
NULL
You can fix your SQL by (adding a FROM table clause and) ordering by Community instead of PrioritySortOrder (though whether the NULL comes first or last depends on your DBMS).

Related

Ignore a column in MS ACCESS query if the WHERE clause is not set

Problem
I've got a dropdown list, which shows all the Article_Group_ID's that are linked to a specific brand, using the following Query:
SELECT TbArticle.Article_Group_ID, TbArticle.Article_Brand_ID
FROM TbArticle
GROUP BY TbArticle.Article_Group_ID, TbArticle.Article_Brand_ID,
HAVING (((TbArticle.Article_Brand_ID)=1))
This works as expected, it returns the following:
Query results
Article_Brand_ID
Article_Group_ID
1
1
1
2
But, if a user does not wish to specify a specific Article_Brand_ID, the query results look like this:
Query
Article_Brand_ID
Article_Group_ID
1
1
2
1
3
1
1
2
As you can see, the same Article_Group_ID is returned three times. Because of this, the user now sees the same group three times, instead of just once. If I were to remove the Article_Brand_ID from the query, the results would look like this:
Article_Group_ID
1
2
Is there any way to achieve the same behavior, by "ignoring" the Article_Brand_ID column, if it's WHERE clause is not set?
Database layout
TbArticle
Article_Brand_ID
Article_Group_ID
1
1
2
1
3
1
1
2
A single query cannot return a variable number of columns. So, strictly speaking you cannot do what you want with a single query. However, if you are willing to accept the second column as NULL when the brand is not provided, then you can adjust the aggregation.
Let me denote the parameter by ?:
SELECT a.Article_Group_ID,
IIF(? IS NOT NULL, a.Article_Brand_ID, NULL) as Article_Brand_ID
FROM TbArticle as a
WHERE a.Article_Brand_ID = ? OR
? IS NULL
GROUP BY a.Article_Group_ID,
IIF(? IS NOT NULL, a.Article_Brand_ID, NULL);
Note: It is usually better to filter before aggregating (i.e. using WHERE) rather than filtering afterwards (i.e. using HAVING).

ORDER BY followed by a number

I took this query from this question.
SELECT *
FROM A
WHERE x='abc'
OR y=0
order by case when x='abc' then 0 else 1 end;
This query supposedly will prioritize x='abc' cases. But I'm really confused why is this happening? Isn't ORDER BY followed by a column name or column number? Also, I researched on the syntax of ORDER BY and they don't tell anything about this. I also tried something like this but it says: "1st ORDER BY term out of range - should be between 1 and 1":
SELECT A
FROM B
ORDER BY 2
So, can anyone explain this query or at least point to a good documentation? Thank you very much.
Well, when an ORDER BY clause is followed by a number, this number will be referenced to the column in the (number) position.
The ORDER BY followed by a CASE EXPRESSION is called conditional ordering, each column will get the value 0 when x is equal to abc and when its not it will get the value 1. After that, the ordering is in ASC , so 0 will always be prioitized before 1.
It will be something like this:
x | y | .... | Here is the new value that will order the query
abc 1 0
ayr 0 1
acz 1 1
.........
So, basically it's like generating a new value.

Comparing row based on contents to another tables rows in Access SQL

Hi I'm working on a project and for time constraint reasons I need to keep working in Access which may be the root of all my problems but maybe there's hope.
I have a database that includes a table ANSWERS filled with input for users "wants" there are multiple columns which each correspond to an answer to a different question asking if they, Don't Care, Want, or Need something.
EG: Answers:
Bacon | Ham | Sausage
________________________________
1 0 0 2
2 2 1 0
3 0 2 0
4 1 1 1
(0 = Don't Care, 1 = Want, 2 = Need)
I want to compare a row from table Answers to the Available table.
EG: Available:
Bacon | Ham | Sausage
________________________________
1 0 1 0
2 0 0 0
3 1 1 1
4 1 1 0
(0 = Unavailable, 1 = Available)
So I would want to compare row 1 from Answers to Available so because row 1 includes sausage=2 then I would want to receive row 3 from Available because sausage=1.
I'd be happy receiving the entire row, or the row ID and a "1" for the rows being a match.
Ultimately I'd need to do this for all each of the rows in Answers.
Any ideas are appreciated, I was thinking using Intersect might work but since that doesn't work in access. I've also considered joining the tables, I could also change data variables or formats if necessary.
Thanks very much
Edit: Don't Care was previously Don't Want. Changed for clarity.
Give this a try:
SELECT tblAnswers.UserID, IIf([tblAnswers].[bacon]>0 And [tblMenus].[Bacon]<>0,[MenuID],Null) AS BaconMenu, IIf([tblAnswers].[Ham]>0 And [tblMenus].[Ham]<>0,[MenuID],Null) AS HamMenu, IIf([tblAnswers].[Sausage]>0 And [tblMenus].[Sausage]<>0,[MenuID],Null) AS SausageMenu
FROM tblAnswers, tblMenus
WHERE (((IIf([tblAnswers].[bacon]>0 And [tblMenus].[Bacon]<>0,[MenuID],Null)) Is Not Null)) OR (((IIf([tblAnswers].[Ham]>0 And [tblMenus].[Ham]<>0,[MenuID],Null)) Is Not Null)) OR (((IIf([tblAnswers].[Sausage]>0 And [tblMenus].[Sausage]<>0,[MenuID],Null)) Is Not Null));
Just paste that into a SQL view make Query window (After changing the table and column names to match yours) You will obviously need to tweak it as reality needs, but it does what you asked for with the data provided.

How can I order results which have some value equals zero in the end, while other results are ascending?

Let me explain: I need to sort a list in ascending order, while results leave less than zero at the end.
Example:
**Field**
2
5
15
19
0
-5
-19
I think I can join result of two queries using UNION, but I want to do using only one, is it possible?
Any answer telling how to order thay way will be appreciated.
Use the following ORDER BY at the end of your normal query (no union)
order by (case when field>0 then 0 else 1 end), field
Or, if your database system's SQL flavor supports implicit conversion of booleans to integers:
order by (field <= 0), field

Best way to count this Data

In short I have 2 tables:
USERS:
------------------------
UserID | Name
------------------------
0 a
1 b
2 c
CALLS:
------------------------
ToUser | Result
------------------------
0 ANSWERED
1 ENGAGED
1 ANSWERED
0 ANSWERED
Etc, etc (i use a numerical referance for result in reality)
I have over 2 million records each detailing a call to a specific client. Currently I'm using Case statements to count each recurance of a particular result AFTER I have already done the quick total count:
COUNT(DISTINCT l_call_log.line_id),
COALESCE (SUM(CASE WHEN l_call_log.line_result = 1 THEN 1 ELSE NULL END), 0) AS [Answered],
COALESCE (SUM(CASE WHEN l_call_log.line_result = 2 THEN 1 ELSE NULL END), 0) AS [Engaged],
COALESCE (SUM(CASE WHEN l_call_log.line_result = 4 THEN 1 ELSE NULL END), 0) AS [Unanswered]
Am I doing 3 scans of the data after my inital total count? if so, is there a way I can do one sweep and count the calls as-per-result in one go?
Thanks.
This would take one full table scan.
EDIT: There's not enough information to answer; because the duplicate removal (DISTINCT) that I missed earlier, we can't tell what strategy that would be used.... especially without knowing the database engine.
In just about every major query engine, each aggregate function is executed per each column per each row, and it may use a cached result (such as COUNT(*) for example).
Is line_result indexed? If so, you could leverage a better query (GROUP BY + COUNT(*) to take advantage of index statistics, though I'm not sure if that's worthwhile depending on your other tables in the query.
There is the GROUP BY construction in SQL. Try:
SELECT COUNT(DISTINCT l_call_log.line_id)
GROUP BY l_call_log.line_result
I would guess it's a table scan, since you don't have any depending subqueries. Run explain on the query to be sure.