SQL select where group by order by distinct - sql-server

I got a one table Search, and columns are:
id(int), title(nvarchar), count(int), expression(nvarchar)
with values:
1, aaa, 5, car
2, aaa, 5, car poster
3, bbb, 8, car magazine
4, bbb, 8, car tv
5, ccc, 12, boat
6, ccc, 12 , boat tv
I need the following result
4, bbb, 8, car tv
3, bbb, 8, car magazine
2, aaa, 5, car poster
1, aaa, 5, car
or better result whatever from 4,3 and 2,1
like this:
3, bbb, 8, car magazine
2, aaa, 5, car poster
I tried this:
SELECT title
FROM
(SELECT *
FROM Search
ORDER BY count DESC)
WHERE expression
LIKE '%car%'
GROUP BY title
I have also tried a DISTINCT

Use a CTE with the ROW_NUMBER function to find the matching rows and order them by descending count along with id for a tie breaker. Then select the first numbered row within each partition (title).
WITH cteFindCar AS (
SELECT id, title, count, expression,
ROW_NUMBER() OVER(PARTITION BY title ORDER BY count DESC, id) AS RowNum
FROM search
WHERE expression LIKE '%car%'
)
SELECT id, title, count, expression
FROM cteFindCar
WHERE RowNum = 1;

Related

Insert dummy rows to fill missing values into a SQL Table

I have this SQL Server table table1 which I want to fill with dummy rows per acct up to latest previous month end date period e.g now would be up to 2021-06-30.
In this example, acct 1 has n number of rows which ends at 2020-05-31, and I want to insert dummy rows with same values for acct and amt with begin_date and end_date incrementing by 1 month up to 06-30-2021.
Let's assume acct 2 already ends at 06-30-2021 so this doesn't need dummy rows to be inserted.
acct,amt,begin_date,end_date
1 , 10, 2020-04-01, 2020-04-30
1 , 10, 2020-05-01, 2020-05-31
2 , 50, 2021-05-01, 2021-05-31
2 , 50, 2021-06-01, 2021-06-30
So for acct 1, I want n number of rows to be inserted from last period of 2020-05-31 up to previous month end which is now 06-30-2021 and I want the amt and acct to remain same. So it would look like this below:
acct,amt,begin_date,end_date
1 , 10, 2020-04-01, 2020-04-30
1 , 10, 2020-05-01, 2020-05-31
1 , 10, 2020-06-01, 2020-06-30
1 , 10, 2020-07-01, 2020-07-31
.............................
.............................
1 , 10, 2021-06-01, 2021-06-30
Based on some data anamolies, I realize I need another condition to the solution. Suppose another column type was added to the table1. So acct and type would be the composite key that identifies each related row hence acct 2 type A and acct 2 type B are not related. So we have the updated table:
acct,type,amt,begin_date,end_date
1, A, 10, 2020-04-01, 2020-04-30
1, A, 10, 2020-05-01, 2020-05-31
2, A, 50, 2021-05-01, 2021-05-31
2, A, 50, 2021-06-01, 2021-06-30
2, B, 50, 2021-01-01, 2021-01-31
2, B, 50, 2021-02-01, 2021-02-28
I would now need dummy rows to be created for acct 2 type B up to 2021-06-30. We already know acct 2 type A would be ok since it already has rows up to 2021-06-30
You can generate the rows using a recursive CTE:
with cte as (
select acct, amt,
dateadd(day, 1, end_date) as begin_date,
eomonth(dateadd(day, 1, end_date)) as end_date
from (select t.*,
row_number() over (partition by acct order by end_date desc) as seqnum
from t
) t
where seqnum = 1 and end_date < '2021-06-30'
union all
select acct, amt, dateadd(month, 1, begin_date),
eomonth(dateadd(month, 1, begin_date))
from cte
where begin_date < '2021-06-01'
)
select *
from cte;
You can then use insert to insert these rows into a table. Or use union all if you simply want a result set with all the rows.
Here is a db<>fiddle.

Enumerate field from existing records in cakePHP

I work with cakePHP and have database table with 3 columns: ID, Name, OrderNo
ID is the primary key which is defined as autoincrement field and contains a number.
Name is a user given value
OrderNo contains a numeric value which is used for sorting SELECT result (ORDER BY ...)
Now, the OrderNo Field is needed because the user have the right, change the order. So far, no problem. If the record on the 4 place on the result should switch the position with the record on place 8, I only flip the value in the field OrderNo and the next result will return the new ordered list.
But now, there is a situation where simply updating will result in a long execution time when I've many records:
When I delete a record, a "place" will be freed. I want close the gap and want enumerate all fields starting with 0.
Sample records;
ID, Name, OrderNo
==================
1, Name1, 5
2, Name2, 4
3, Name3, 3
4, Name4, 2
5, Name5, 1
I remove ID 3 which results in
ID, Name, OrderNo
==================
1, Name1, 5
2, Name2, 4
4, Name4, 2
5, Name5, 1
Which should be
ID, Name, OrderNo
==================
1, Name1, 4
2, Name2, 3
4, Name4, 2
5, Name5, 1
Currently I would loop all existing records (sorted by OrderNo) and would write the field OrderNo with a value which I would increase every round but this solution isn't really efficient. I tested it with 5000 records and it tooks 40 seconds to finish.
Is there maybe a cakePHP solution based on sql syntax which can do that job much more faster?
Maybe the tree behavior is what you looking for. http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html

Add new rows to resultset in MSSQL

I am running a SQL query in MSSQL 2008 R2 which should always return a consistent resultset, meaning that all dates within a selected date range should be shown, although there are no rows/values in the database for a particular date within the date range. It should for example look like this for the dates 2013-07-03 - 2013-07-04 when there are values for id 1 and 2.
Scenario 1
Date-hour, value, id
2013-07-03-1, 10, 1
2013-07-03-2, 12, 1
2013-07-03-...
2013-07-03-24, 9, 1
2013-07-04-1, 10, 1
2013-07-04-2, 10, 1
2013-07-04-...
2013-07-04-24, 10, 1
2013-07-03-1, 11, 2
2013-07-03-2, 12, 2
2013-07-03-...
2013-07-03-24, 9, 2
2013-07-04-1, 10, 2
2013-07-04-2, 12, 2
2013-07-04-...
2013-07-04-24, 10, 2
However, if id 2 is missing values for 2013-07-04, I will normally only get a resultset which looks like this:
Scenario 2
Date-hour, value, id
2013-07-03-1, 10, 1
2013-07-03-2, 12, 1
2013-07-03-...
2013-07-03-24, 9, 1
2013-07-04-1, 10, 1
2013-07-04-2, 10, 1
2013-07-04-...
2013-07-04-24, 10, 1
2013-07-03-1, 11, 2
2013-07-03-2, 12, 2
2013-07-03-...
2013-07-03-24, 9, 2
Scenario 2 will create an inconsistent resultset which will affect the output. Is there any way to make the SQL query always return as scenario 1 even when there are missing values, so at least to return NULL if there are no values for a specific date within the date range. If the resultset returns id 1 and 2 then all dates for id 1 and 2 should be covered. If id 1, 2 and 3 are returned then all dates for id 1, 2 and 3 should be covered.
I have two tables which look like this:
tbl_measurement
id, date, hour1, hour2, ..., hour24
tbl_plane
planeId, id, maxSpeed
The SQL query I am running look like this:
SELECT DISTINCT hour00_01, hour01_02, mr.date, mr.id, maxSpeed
FROM tbl_measurement as mr, tbl_plane as p
WHERE (date >= '2013-07-03' AND date <= '2013-07-04') AND p.id = mr.id
GROUP BY mr.id, mr.date, hour00_01, hour01_02, p.maxSpeed
ORDER BY mr.id, mr.date
I have been looking around quite a bit, and perhaps PIVOT tables are the way to solve this? Could you please help me out? I would appreciate if you can help me out with how to write the SQL query for this purpose.
You can use a recursive CTE to generate a list of dates. If you cross join that with planes, you get one row per date per plane. With a left join, you can link in measurements if they exist. A left join will leave the row even if no measurement is found.
For example:
declare #startDt date = '2013-01-01'
declare #endDt date = '2013-06-30'
; with AllDates as
(
select #startDt as dt
union all
select dateadd(day, 1, dt)
from AllDates
where dateadd(day, 1, dt) <= #endDt
)
select *
from AllDates ad
cross join
tbl_plane p
left join
(
select row_number() over (partition by Id, cast([date] as date) order by id) rn
, *
from tbl_measurement
where m.inputType = 'forecast'
) m
on p.Id = m.Id
and m.date = ad.dt
and m.rn = 1 -- Only one per day
where p.planeType = 3
option (maxrecursion 0)

TSQL - Select the rows with the higher count and when count is the same, the row with the higher id value

HELP!!! I'm stumped and have tried several options to no avail...
I need to return one row for each Pub_id, and the row that is returned should be the one with the higher Count and when there is more than one row with the highest count, I need the one with the higher price_id.
I have populated a table with this data...
pub_id, price_id, count
7, 59431, 5
22, 39964, 4
39, 112831, 3
39, 120715, 2
47, 95359, 2
74, 142825, 5
74, 106688, 5
74, 37514, 1
and This is what I need to return...
pub_id, price_id, count
7, 59431, 5
22, 39964, 4
39, 112831, 3
47, 95359, 2
74, 142825, 5
;WITH T
AS (SELECT *,
ROW_NUMBER() OVER (PARTITION BY pub_id
ORDER BY [count] DESC, price_id DESC) AS rn
FROM your_table)
SELECT pub_id,
[count],
price_id
FROM T
WHERE rn=1
Do you want something like this
select pub_id,
Count,
Price_Id
from (select Pub_id,
max(count),
Price_Id
from table_name
group by Pub_id) der_tab
group by Pub_id,
Count
having Price_id = max(price_Id)

Calculate previous SUM value

I have 2 SQL Server 2005 tables: Names and Scores
Names table:
NameID, Name, Age
1, 'John', 23
2, 'Ryan', 20
Scores table:
ScoreID, NameID, ScoreDate, ScoreValue
1, 1, 01/01/2011, 250
2, 1, 02/01/2011, 300
3, 1, 03/01/2011, 100
4, 2, 01/01/2011, 150
5, 2, 02/01/2011, 350
6, 2, 03/01/2011, 200
I want to get for a given month:
Name, Age, current ScoreValue, sum(ScoreValue) for previous months
Something like this form the month of february:
John, 23, 300, 550
Ryan, 20, 350, 500
Think this is what you want:
select n.Name,
s1.ScoreId,
s1.nameId,
s1.ScoreValue,
sum(s2.ScoreValue) Prevmonths
from names n
inner join scores s1 on n.NameId = s1.NameId
left join scores s2 -- make left join in case no previous month
on s1.NameId = s2.NameId
and s1.ScoreDate >= s2.ScoreDate -- >= means include current onth
group by n.Name,
s1.ScoreId,
s1.nameId,
s1.ScoreValue
GJ

Resources