SQL order by - sql

I need to order a table conditioned by date and i cant do it!! :(
i have a field (codigo) that if the year of the date(passed by parameter) is less than 2010 then it is composed like this : "FAC-00123-10", then i nedd to order by this "00123"...
Otherwise, if the year code is bigger than 2010, the field (Codigo) is created like this "FT 11/123" and then i need to order by this "123"
How can i do this?!

You can use a case when statement to decide what to order by, this uses a simple substring but in reality this probably isnt good enough and you may need to parse the bit you are interested in a little bit better..
select * from table order by
case when DatePart(year,#date) < 2010 then substring(codigo,4,5)
else substring(condigo,3,2) end

Related

How to specify a group of years in a table in SQL

Basic SQL question about specifying a group of years in a table. Working on a database and it is wanting me to list the author, title, publication date and retail price. I have that part down but its also ask to output all titles that start with "D" and were published in the 1970s.
I have the first part down: (this is how we are taught btw)
SELECT `fAuthorID`,`fTitle`,`fPubYear`,`fRetailPrice`
FROM `tBooks`
WHERE
But I cant seem to be able to get it to output the authors with a "D" and years 1970-1979 to display.
Assuming fpubyear is a number (integer) column, the correct way of querying for a continuous range of years is to use the BETWEEN operator.
SELECT fauthorID, fTitle, fPubYear, fReatailPrice
FROM tbooks
WHERE fTitle Like 'D%'
AND fPubYear BETWEEN 1970 and 1979;
The between operator includes both ends. It has the added benefit that an index on fpubyear can be used to quickly find the matching rows - which is not the case if the number first needs to be converted to a string to be able to apply the LIKE operator on it.
LIKE is for character values ("strings"), it should not be used with other types - especially not when relying on the evil implicit data type conversion. Other database would simply reject applying like on a number column.
SELECT fauthorID, fTitle, fPubYear, fReatailPrice
FROM tbooks
WHERE fTitle Like 'D%' AND fPubYear Like '197_'
Hi Dewie You an use this query,
SELECT fAuthorID,fTitle,fPubYear,fRetailPrice
FROM tBooks
WHERE fTitle like 'D%' and fPubYear like '%197%';
Hope this will give you result. Any issues just let me know

Access 2010 conditional selection in query

I'm trying to complete my university coursework but i'm stuck with the selection process in a query.
Running Access 2010, I have to select the following fields:
Asset ID, Asset Description, Problem ID, Current Helpdesk person allocated to the problem or the date solved and the solution given.
How can I do a conditional select so that basically like it says, IF solution date is filled in, fetch the date and description. Otherwize, fetch the Helpdesk person who is assigned.
Please assume that all fields are in the Problems table and I can adapt from there as needed, just need a heads up on how to select a column in one case and if the case resolves to false, select an alternative column.
I have not much idea about MS Access, but you can try it with IIF() function like below as MS Access doesn't support CASE WHEN clause. You can also use Format() function to convert date in string with whatever format you want.
SELECT Asset_ID,
Asset_Description,
Problem_ID
IIF(IsNull(Date), Helpdesk_Person, CStr(Date) + Description) as Solution
FROM Problems

SQL statement HAVING MAX(some+thing)=some+thing

I'm having trouble with Microsoft Access 2003, it's complaining about this statement:
select cardnr
from change
where year(date)<2009
group by cardnr
having max(time+date) = (time+date) and cardto='VIP'
What I want to do is, for every distinct cardnr in the table change, to find the row with the latest (time+date) that is before year 2009, and then just select the rows with cardto='VIP'.
This validator says it's OK, Access says it's not OK.
This is the message I get: "you tried to execute a query that does not include the specified expression 'max(time+date)=time+date and cardto='VIP' and cardnr=' as part of an aggregate function."
Could someone please explain what I'm doing wrong and the right way to do it? Thanks
Note: The field and table names are translated and do not collide with any reserved words, I have no trouble with the names.
Try to think of it like this - HAVING is applied after the aggregation is done.
Therefore it can not compare to unaggregated expressions (neither for time+date, nor for cardto).
However, to get the last (principle is the same for getting rows related to other aggregated functions as weel) time and date you can do something like:
SELECT cardnr
FROM change main
WHERE time+date IN (SELECT MAX(time+date)
FROM change sub
WHERE sub.cardnr = main.cardnr AND
year(date)<2009
AND cardto='VIP')
(assuming that date part on your time field is the same for all the records; having two fields for date/time is not in your best interest and also using reserved words for field names can backfire in certain cases)
It works because the subquery is filtered only on the records that you are interested in from the outer query.
Applying the same year(date)<200 and cardto='VIP' to the outer query can improve performance further.

Sorting SQL by first two characters of fields

I'm trying to sort some data by sales person initials, and the sales rep field is 3 chars long, and is Firstname, Lastname and Account type. So, Bob Smith would be BS* and I just need to sort by the first two characters.
How can I pull all data for a certain rep, where the first two characters of the field equals BS?
In some databases you can actually do
select * from SalesRep order by substring(SalesRepID, 1, 2)
Othere require you to
select *, Substring(SalesRepID, 1, 2) as foo from SalesRep order by foo
And in still others, you can't do it at all (but will have to sort your output in program code after you get it from the database).
Addition: If you actually want just the data for one sales rep, do as the others suggest. Otherwise, either you want to sort by the thing or maybe group by the thing.
What about this
SELECT * FROM SalesTable WHERE SalesRepField LIKE 'BS_'
I hope that you never end up with two sales reps who happen to have the same initials.
Also, sorting and filtering are two completely different things. You talk about sorting in the question title and first paragraph, but your question is about filtering. Since you can just ORDER BY on the field and it will use the first two characters anyway, I'll give you an answer for the filtering part.
You don't mention your RDBMS, but this will work in any product:
SELECT
my_columns
FROM
My_Table
WHERE
sales_rep LIKE 'BS%'
If you're using a variable/parameter then:
SELECT
my_columns
FROM
My_Table
WHERE
sales_rep LIKE #my_param + '%'
You can also use:
LEFT(sales_rep, 2) = 'BS'
I would stay away from:
SUBSTRING(sales_rep, 1, 2) = 'BS'
Depending on your SQL engine, it might not be smart enough to realize that it can use an index on the last one.
You haven't said what DBMS you are using. The following would work in Oracle, and something like them in most other DBMSs
1) where sales_rep like 'BS%'
2) where substr(sales_rep,1,2) = 'BS'
SELECT * FROM SalesRep
WHERE SUBSTRING(SalesRepID, 1, 2) = 'BS'
You didn't say what database you were using, this works in MS SQL Server.

SQL Group By

If I have a set of records
name amount Code
Dave 2 1234
Dave 3 1234
Daves 4 1234
I want this to group based on Code & Name, but the last Row has a typo in the name, so this wont group.
What would be the best way to group these as:
Dave/Daves 9 1234
As a general rule if the data is wrong you should fix the data.
However if you want to do the report anyway you could come up with another criteria to group on, for example LEFT(Name, 4) would perform a grouping on the first 4 characters of the name.
You may also want to consider the CASE statement as a method (CASE WHEN name = 'Daves' THEN 'Dave' ELSE name), but I really don't like this method, especially if you are proposing to use this for anything else then a one-off report.
If it's a workaround, try
SELECT cname, SUM(amount)
FROM (
SELECT CASE WHEN NAME = 'Daves' THEN 'Dave' ELSE name END AS cname, amount
FROM mytable
)
GROUP BY cname
This if course will handle only this exact case.
For MySQL:
select
group_concat(distinct name separator '/'),
sum(amount),
code
from
T
group by
code
For MSSQL 2005+ group_concat() can be implemented as .NET custom aggregate.
Fix the typo? Otherwise grouping on the name is going to create a new group.
Fixing your data should be your highest priority instead of trying to devise ways to "work around" it.
It should also be noted that if you have this single typo in your data, it is likely that you have (or will have at some point in the future) even more screwy data that will not cleanly fit into your code, which will force you to invent more and more "work arounds" to deal with it, when you should be focusing on the cleanliness of your data.
If the name field is suppose to be a key then the assumption has to be that Dave and Daves are two different items all together, and thus should be grouped differently. If however it is a typo, then as other have suggested, fix the data.
Grouping on a freeform entered text field if that is what this is, will always have issues. Data entry is never 100%.
To me it makes more sense to group on the code alone if that is the key field and leave name out of the grouping all together.