how to write the sql command? - sql

table one:
field one field two
1 1-1
2 1-2
3 1-5
4 1-3
4 1-6
4 1-2
5 1-0
using the sql command to get the results as the following table.
field one field two
5 1-0
1 1-1
2 1-2
4 1-2
4 1-3
4 1-6
3 1-5
ps: the condition is selecting field two order by asc . but if the result have the same field one.then put the field two together. and asc them.

With regards to your second question (actually sort properly as well) it gets a tad bit more complex.
This version works on Sql-Server (don't know what you are using and the functions may differ)
select tableOne.fieldOne, tableOne.fieldTwo
from tableOne
inner join
(select
fieldOne,
MIN(Convert(int, LEFT(tableOne.FieldTwo, CHARINDEX('-', tableOne.fieldTwo)-1))) as LeftPartMin,
MIN(Convert(int, SubString(tableOne.FieldTwo, CHARINDEX('-', tableOne.fieldTwo)+1, 100))) as RightPartMin
from tableOne group by fieldOne
) b
on (b.fieldOne = tableOne.fieldOne)
order by b.LeftPartMin, b.RightPartMin, fieldOne, Convert(int, LEFT(tableOne.FieldTwo, CHARINDEX('-', tableOne.fieldTwo)-1)), Convert(int, SubString(tableOne.FieldTwo, CHARINDEX('-', tableOne.fieldTwo)+1, 100))
You can test this by adding the following 2 records at the end in your table:
4 1-20
2 1-10
This also revealed an error in the first solution: you need to sort one fieldOne as well! (as the second sort argument) to make sure groups with the same fieldOne end up together (edited other answer to correct this)

Haven't checked the syntax but something along these lines should do it:
select tableOne.fieldOne, tableOne.fieldTwo, b.SortField from tableOne
inner join
(select fieldOne, min(fieldTwo) as SortField from tableOne group by fieldOne) b
on (b.fieldOne = tableOne.fieldOne)
order by b.SortField, tableOne.fieldOne, tableOne.fieldTwo
In essence: for each fieldOne find the lowest value in the group and use that as primary sortfield for all records in the group. Within the group sort on the actual value in fieldtwo
There are still potential issues left though: 1-10 will sort between 1-1 and 1-2
If you also want to resolve that you need to split up fieldtwo and convert to ints.
In all cases you might want to rethink if this datamodel is really setup the way you want/need

Related

SQL Server query order by sequence serie

I am writing a query and I want it to do a order by a series. The first seven records should be ordered by 1,2,3,4,5,6 and 7. And then it should start all over.
I have tried over partition, last_value but I cant figure it out.
This is the SQL code:
set language swedish;
select
tblridgruppevent.id,
datepart(dw,date) as daynumber,
tblRidgrupper.name
from
tblRidgruppEvent
join
tblRidgrupper on tblRidgrupper.id = tblRidgruppEvent.ridgruppid
where
ridgruppid in (select id from tblRidgrupper
where corporationID = 309 and Removeddate is null)
and tblridgruppevent.terminID = (select id from tblTermin
where corporationID = 309 and removedDate is null and isActive = 1)
and tblridgrupper.removeddate is null
order by
datepart(dw, date)
and this is a example the result:
5887 1 J2
5916 1 J5
6555 2 Junior nybörjare
6004 2 Morgonridning
5911 3 J2
6467 3 J5
and this is what I would expect:
5887 1 J2
6555 2 Junior nybörjare
5911 3 J2
5916 1 J5
6004 2 Morgonridning
6467 3 J5
You might get some value by zooming out a little further and consider what you're trying to do and how else you might do it. SQL tends to perform very poorly with row by row processing as well as operations where a row borrows details from the row before it. You also could run into problems if you need to change what range you repeat at (switching from 7 to 10 or 4 etc).
If you need a number there somewhat arbitrarily still, you could add ROW_NUMBER combined with a modulo to get a repeating increment, then add it to your select/where criteria. It would look something like this:
((ROW_NUMBER() OVER(ORDER BY column ASC) -1) % 7) + 1 AS Number
The outer +1 is to display the results as 1-7 instead of 0-6, and the inner -1 deals with the off by one issue (the column starting at 2 instead of 1). I feel like there's a better way to deal with that, but it's not coming to me at the moment.
edit: Looking over your post again, it looks like you're dealing with days of the week. You can order by Date even if it's not shown in the select statement, that might be all you need to get this working.
The first seven records should be ordererd by 1,2,3,4,5,6 and 7. And then it should start all over.
You can use row_number():
order by row_number() over (partition by DATEPART(dw, date) order by tblridgruppevent.id),
datepart(dw, date)
The second key keeps the order within a group.
You don't specify how the rows should be chosen for each group. It is not clear from the question.

SQL to return records that do not have a complete set according to a second table

I have two tables. I want to find the erroneous records in the first table based on the fact that they aren't complete set as determined by the second table. eg:
custID service transID
1 20 1
1 20 2
1 50 2
2 49 1
2 138 1
3 80 1
3 140 1
comboID combinations
1 Y00020Y00050
2 Y00049Y00138
3 Y00020Y00049
4 Y00020Y00080Y00140
So in this example I would want a query to return the first row of the first table because it does not have a matching 49 or 50 or (80 and 140), and the last two rows as well (because there is no 20). The second transaction is fine, and the second customer is fine.
I couldn't figure this out with a query, so I wound up writing a program that loads the services per customer and transid into an array, iterates over them, and ensures that there is at least one matching combination record where all the services in the combination are present in the initially loaded array. Even that came off as hamfisted, but it was less of a nightmare than the awkward outer joining of multiple joins I was trying to accomplish with SQL.
Taking a step back, I think I need to restructure the combinations table into something more accommodating, but I still can't think of what the approach would be.
I do not have DB2 so I have tested on Oracle. However listagg function should be there as well. The table service is the first table and comb the second one. I assume the service numbers to be sorted as in the combinations column.
select service.*
from service
join
(
select S.custid, S.transid
from
(
select custid, transid, listagg(concat('Y000',service)) within group(order by service) as agg
from service
group by custid, transid
) S
where not exists
(
select *
from comb
where S.agg = comb.combinations
)
) NOT_F on NOT_F.custid = service.custid and NOT_F.transid = service.transid
I dare to say that your database design does not conform to the first normal form since the combinations column is not atomic. Think about it.

SQL Query - Limited by another SQL query of a different data type

I need some help on this one. I have a query that I need to make work but I need to limit it by the results of another query.
SELECT ItemID, ItemNums
FROM dbo.Tables
ItemNums is a varchar field that is used to store the strings of the various item numbers.
This produces the following.
ItemID ItemNums
1 1, 4, 5
2 1, 3, 4, 5
3 2
4 4
5 1
I have another table that has each item number as an INT that I need to use to pull all ItemIDs that have the associated ItemNums
Something like this.
SELECT *
FROM dbo.Tables
WHERE ItemNums IN (4,5)
Any help would be appreciated.
If possible, you should change your database schema. In general, it's not good to store comma delimited lists in a relational database.
However, if that's not an option, here's one way using a join with like:
select *
from dbo.Tables t
join dbo.SecondTable st on ', '+t.ItemNums+',' like '%, '+st.ItemNumId+',%'
This concatenates commas to the beginning and end of the itemnums to ensure you only match on the specific ids.
I personally would recommend normalizing your dbo.tables.
It would be better as:
ItemID ItemNums
1 1
1 4
1 5
2 1
etc.
Then you can use a join or a sub query to pull out the rows with ItemNums in some list.
Otherwise, it's going to be a mess and not very fast.

sqlite query unsorted result

I have list of Ids 31165,31160,31321,31322,31199,31136 which is dynamic.
When I run query
select id,name from master_movievod where id in(31165,31160,31321,31322,31199,31136);
I get following result
31136|Independence Day
31160|Planet of the Apes
31165|Mrs. Doubtfire
31199|Moulin Rouge
31321|Adult Movie 2
31322|Adult Movie 3
This is sorted list in ascending order.
I want the list in the same order which I give as input like
31165|Mrs. Doubtfire
31160|Planet of the Apes
31321|Adult Movie 2
31322|Adult Movie 3
31199|Moulin Rouge
31136|Independece Day
Without an order by clause, there's no guarantee on the order a database returns the results to you. SQLite, unfortunately, doesn't have something like MySQL's field for custom sorting, but you can jimmy-rig something with a case expression:
SELECT id, name
FROM master_movievod
WHERE id IN (31165, 31160, 31321, 31322, 31199, 31136)
ORDER BY CASE ID WHEN 31165 THEN 0
WHEN 31160 THEN 1
WHEN 31321 THEN 2
WHEN 31322 THEN 3
WHEN 31199 THEN 4
WHEN 31136 THEN 5
END ASC
Unfortunately, SQLite does not have an option like MySQL's FIELD for doing a custom ordering. You are left with two options. The first is that you could create a custom table containing the ordering you want and use that to sort. This option isn't very attractive. The second (and easier) option is to use ORDER BY CASE to achieve the order you want:
SELECT id, name FROM master_movievod
WHERE id IN (31165,31160,31321,31322,31199,31136)
ORDER BY
CASE id
WHEN 31165 THEN 0
WHEN 31160 THEN 1
WHEN 31321 THEN 2
WHEN 31322 THEN 3
WHEN 31199 THEN 4
WHEN 31136 THEN 5
END ASC

Get MAX() on repeating IDs

This is how my query results look like currently. How can I get the MAX() value for each unique id ?
IE,
for 5267139 is 8.
for 5267145 is 4
5267136 5
5267137 8
5267137 2
5267139 8
5267139 5
5267139 3
5267141 4
5267141 3
5267145 4
5267145 3
5267146 1
5267147 2
5267152 3
5267153 3
5267155 8
SELECT DISTINCT st.ScoreID, st.ScoreTrackingTypeID
FROM ScoreTrackingType stt
LEFT JOIN ScoreTracking st
ON stt.ScoreTrackingTypeID = st.ScoreTrackingTypeID
ORDER BY st.ScoreID, st.ScoreTrackingTypeID DESC
GROUP BY will partition your table into separate blocks based on the column(s) you specify. You can then apply an aggregate function (MAX in this case) against each of the blocks -- this behavior applies by default with the below syntax:
SELECT First_column, MAX(Second_column) AS Max_second_column
FROM Table
GROUP BY First_column
EDIT: Based on the query above, it looks like you don't really need the ScoreTrackingType table at all, but leaving it in place, you could use:
SELECT st.ScoreID, MAX(st.ScoreTrackingTypeID) AS ScoreTrackingTypeID
FROM ScoreTrackingType stt
LEFT JOIN ScoreTracking st ON stt.ScoreTrackingTypeID = st.ScoreTrackingTypeID
GROUP BY st.ScoreID
ORDER BY st.ScoreID
The GROUP BY will obviate the need for DISTINCT, MAX will give you the value you are looking for, and the ORDER BY will still apply, but since there will only be a single ScoreTrackingTypeID value for each ScoreID you can pull it out of the ordering.