how to search data using "like" in sql server - sql-server

I typed a word "boat", so i need records that start with boat and also that contains "boat".but starting with "boat" must appear first
i tried following
Select AsiccCodeId,AsiccDescription
FROM AsiccCodeMaster c
WHERE c.AsiccDescription like 'boat%' or c.AsiccDescription like '%boat%'
and
select a.* from
(
Select AsiccCodeId,AsiccDescription
FROM AsiccCodeMaster c
WHERE c.IsActive = 1 and (GoodFor = 'M' or GoodFor = 'B')
and c.AsiccDescription like 'Unmilled%'
UNION
Select AsiccCodeId,AsiccDescription
FROM AsiccCodeMaster c
WHERE c.IsActive = 1 and (GoodFor = 'M' or GoodFor = 'B')
and c.AsiccDescription like '%Unmilled%'
)a
but it gives me
4137 Combustion Boats
6360 Boat, Fibre
6361 Boat, Rubber - Motorized
6362 Boat, Wooden Canal Boats
6363 Boat, Wooden With Engine
6370 Wooden Boats Body Building
6374 Boat, Rowing / Sports
6375 Boat, Rubber - Nonmotorized
6376 Boat, Wooden Without Engine-Others
6379 Parts Of Ships, Boats Etc., N.E.C
6391 Ships, Boats & Other Vessels, N.E.C
6394 Ships, Boats & Other Vessels, N.E.C
i need records that starts with "boat" first and then records that contains "boat"

Use a CASE statement in an Order By clause
SELECT AsiccCodeId,AsiccDescription
FROM AsiccCodeMaster c
WHERE c.AsiccDescription like '%boat%'
ORDER BY CASE WHEN c.AsiccDescription like 'boat%' THEN 0 ELSE 1 END, c.AsiccDescription
Since you want titles that start with 'boat' to appear first, the CASE statement will prioritize those first. It looks at each record and, if the description starts with 'boat', assigns it a sort value of 0, otherwise it assigns it a sort value of 1. ORDER BY sorts ascending by default, so it will put all the 0s (the ones that start with 'boat') before all the 1s (the remaining records)

You need to give your results some ordering!
SELECT a.*
FROM
(
SELECT
AsiccCodeId, AsiccDescription, Sequence = 1
FROM AsiccCodeMaster c
WHERE c.IsActive = 1 AND (GoodFor = 'M' or GoodFor = 'B')
AND c.AsiccDescription LIKE 'Boat%'
UNION
SELECT
AsiccCodeId, AsiccDescription, Sequence = 2
FROM AsiccCodeMaster c
WHERE c.IsActive = 1 AND (GoodFor = 'M' or GoodFor = 'B')
AND c.AsiccDescription LIKE '%Boat%'
) a
ORDER BY a.Sequence

Related

Will these two MS queries give me the same output?

I'm updating some queries as an assignment for work. The bottom query is the updated version with different syntax, and the top is the old query. I just want to double check that the two queries will end with the same results:
SELECT a.breed
FROM dogs a, cats b, fish c
WHERE a.breed = b.breed AND a.tail = 0 AND b.size = c.size AND c.gills = 0 AND c.fin = #fin
----
SELECT a.breed
FROM dogs a
INNER JOIN cats b ON a.breed = b.breed
INNER JOIN fish c ON b.size = c.size
WHERE c.gills = 0 AND a.tail = 0 AND c.fin = #fin
Edit 1: fixed the format of the question to better represent what I meant. I changed the names of the tables and columns just in case.
Yes, these queries will return the same results.

Need to return the first instance found, instead of all

I have a query that I have had make do over the last few years which heavily leans on the users entering in data in a somewhat correct order (i know, first mistake).
The idea is that the users enter a item with the category of CRT in the first 7 lines...and only one. Some times there may be others with this category, but i only want the first one. Now, users sometimes enter the item in after the first 7 rows...leading to another problem. Here is my original query:
Select distinct
d.Job_Number as Rig,
case d.Customer_Name
when 'case' then 'diff case'
else '******'
end as Parent_Customer,
d.Customer_Name,
case d.Reference_Location2
when 'case' then 'diff case'
else '******'
end as Size,
case d.Office_code
when 'case' then 'diff case'
else '****'
end as Office,
d.Rental_Ticket,
case d.job_type
when 'case' then 'diff case'
else '0'
end as Billable,
d.Reference_Location5 as TT
from HP_View_DEL_Ticket_Header_Master as d
left join CSView_INVC_Header_Master as i --left join to report jobs that have not been invoiced
on d.Rental_Ticket = i.Rental_Ticket_or_Tag_Number
join CSView_DEL_Ticket_Lines_Master as l
on d.Rental_Ticket = l.Rental_Ticket
where (d.Ticket_Month between 7 and 7 and d.Ticket_Year = 2017)-- or (d.Ticket_Month between 12 and 12 and d.Ticket_Year = 2016))
and d.Rental_Ticket not in (select dticket from deltick_void)
and d.Ticket_Type = 'D'
and d.Posted_Flag = -1
and l.Row_Counter between 1 and 7 --Currently how I get the correct record, problem is its sometimes not entered in the first 7 rows.
and l.Category_Code = 'CRT'
order by Parent_Customer
I am needing one Ticket number, to one CRT item (the CRT first item). I've tried doing something in the where clause to find the top CRT items but didn't work the way i figured it would.
Any help would be great.
Thanks
BD
EDIT:
Expected OUTPUT
Rig Parent_Customer Customer_Name Size Office Rental_Ticket Billable TT
RIG 642 A A 5 to 5.5 City 12627 0 YES
RIG 525 B B 5 1/2 City 2 12628 0 YES
RIG 603 C C 9 5/8 City 3 12634 0 NO
Incorrect OUTPUT:
Rig Parent_Customer Customer_Name Size Office Rental_Ticket Billable TT
RIG 642 A A 5 to 5.5 City 12627 0 YES
RIG 642 A A 5 to 5.5 City 12627 0 YES
Because the query finds more than one 'CRT' on the Rental Ticket, it returns two records that are the same for the columns I have selected. I am wanting to use ONLY the first one it finds.

Changing character in a string of characters

I was wondering regarding how to edit the following column that exists in oracle DB
PPPPFPPPPPPPPPPPPPPPPPPPPPPPPFPPPPPPPP
I want to only set the 5th F with P without affecting other structure.
I've around 700 records and I want to change that position (5th) on all users to P
I was thinking of PLSQL instead of a query, so could you please advice.
Thanks
Use REGEXP_REPLACE:
> SELECT REGEXP_REPLACE('PPPPFPPPPPPPPPPPPPPPPPPPPPPPPFPPPPPPPP', '^(\w{4}).(.*)', '\1P\2') AS COL_REGX FROM dual
COL_REGX
--------------------------------------
PPPPPPPPPPPPPPPPPPPPPPPPPPPPPFPPPPPPPP
Klashxx answer is a good one - REGEXP_REPLACE is the way to go. Old fashioned way built up bit by bit so you can see what's going on :
WITH
test_data (text)
AS (SELECT '1234F1234F1234F1234F1234F1234F1234' FROM DUAL
)
SELECT
text
,INSTR(text,'F',1,5) --fifth occurence
,SUBSTR(text,1,INSTR(text,'F',1,5)-1) --substr up to that point
,SUBSTR(text,1,INSTR(text,'F',1,5)-1)||'P' --add P
,SUBSTR(text,1,INSTR(text,'F',1,5)-1)||'P'||SUBSTR(text,INSTR(text,'F',1,5)+1) --add remainder of string
FROM
test_data
;
So what you're trying to do would be something like
UPDATE <your table>
SET <your column> = SUBSTR(<your column>,1,INSTR(<your column>,'F',1,5)-1)||'P'||SUBSTR(<your column>,INSTR(<your column>,'F',1,5)+1)
..assuming you want to update all rows
The solution below looks for the first five characters at the beginning of the input string. If found, it keeps the first four unchanged and it replaces the fifth with the letter P. Note that if the input string is four characters or less, it is left unchanged. (This includes NULL as the input string, shown in the WITH clause which creates sample strings and also in the output - note that the output has FIVE rows, even though there is nothing visible in the last one.)
with
test_data ( str ) as (
select 'ABCDEFGH' from dual union all
select 'PPPPF' from dual union all
select 'PPPPP' from dual union all
select '1234' from dual union all
select null from dual
)
select str, regexp_replace(str, '^(.{4}).', '\1P') as replaced
from test_data
;
STR REPLACED
-------- --------
ABCDEFGH ABCDPFGH
PPPPF PPPPP
PPPPP PPPPP
1234 1234
5 rows selected.
Flip the 5th 'bit' to a 'P' where it's currently an 'F'.
update table
set column = regexp_replace(column , '^(.{4}).', '\1P')
where regexp_like(column , '^.{4}F');

SQL Server MAX and GROUP BY not playing nicely together

I have a T-SQL query of the form:
SELECT f.fizz_name, b.buzz_version, fu.foo_name
FROM fizz f
INNER JOIN buzz b
ON f.fizz_id = b.fizz_id
INNER JOIN foo fu
ON b.buzz_id = fu.buzz_id
WHERE f.bar LIKE 'YES'
When I run this query I get the following results:
fizz_name buzz_version foo_name
====================================
Gamma 0.3.960 Test
Gamma 0.3.961 Test
Gamma 0.3.960 Test
Gamma 0.3.961 Test
Delta 0.3.2588 Test
Delta 0.3.2589 Test
Delta 0.3.2588 Test
Delta 0.3.2589 Test
Echo 2.2.38 Test
Echo 2.2.38 Test
The problem with this is that it contains a lot of entries that I don't care about. In reality I only care about the largest buzz_version for each fizz instance, in other words:
fizz_name buzz_version foo_name
====================================
Gamma 0.3.961 Test
Delta 0.3.2589 Test
Echo 2.2.38 Test
...because "2.2.38" is the latest/lexiconographically-highest buzz_version for Echo, and same for the other fizzes.
So I am trying to use GROUP BY in concert with MAX to fetch these values like so:
SELECT f.fizz_name, MAX(b.buzz_version), fu.foo_name
FROM fizz f
INNER JOIN buzz b
ON f.fizz_id = b.fizz_id
INNER JOIN foo fu
ON b.buzz_id = fu.buzz_id
WHERE f.bar LIKE 'YES'
GROUP BY b.buzz_version
But that gives me an error:
Column 'fizz.fizz_name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Where am I going wrong, and why?
You are grouping by the aggregate in your query. You need to group by the scalar columns instead. In this case, group by f.fizz_name, fu.foo_name
You want one result row per fizz_name, so you must group by fizz_name. You show MAX(b.buzz_version) with it and must decide which fu.foo_name to show. E.g.:
SELECT f.fizz_name, MAX(b.buzz_version), MAX(fu.foo_name)
FROM fizz f
INNER JOIN buzz b ON f.fizz_id = b.fizz_id
INNER JOIN foo fu ON b.buzz_id = fu.buzz_id
WHERE f.bar LIKE 'YES'
GROUP BY f.fizz_name;

T-SQL field parsing

There is a field in a 3rd party database that I need to group on for a report I'm writing. The field can contain a few different types of data. First it could contain a 3 digit number. I need to break these out into groups such as 101 to 200 and 201 to 300. In addition to this the field could also be prefaced with a particular letter such a M or K then a few numbers. It is defined as VARCHAR(8) and any help in how I could handle both cases where it may start with a particular letter or fall within a numeric range would be appreciated. If I could write it as a case statement and return a department based either on the numeric value or the first letter that would be the best so I can group in my report.
Thanks,
Steven
If I could write it as a case statement and return a department based either on the numeric value or the first letter that would be the best so I can group in my report.
case when substring( field, 1, 1 ) = 'M' then ...
when substring( field, 1, 1 ) = 'K" then ...
else floor( (cast( field as int) - 1 ) / 100) end
select ....
group by
case when substring( field, 1, 1 ) = 'M' then ...
when substring( field, 1, 1 ) = 'K" then ...
else floor( (cast( field as int) - 1 ) / 100) end
Matt Hamilton asks,
Any reason why you've opted to use substring(field, 1, 1) rather than simply left(field, 1)? I notice that #jms did it too, in the other answer.
I know substring is specified in ANSI-92; I don't know that left is. And anyway, left isn't a primitive, as it can be written in terms of substring, so using substring seems a little cleaner.
select
CASE (CASE WHEN substring(field,1,1) between 0 and 9 then 'N' Else 'C' END)
WHEN 'N' THEN
CASE field
WHEN ... THEN ...
WHEN ... THEN ...
END
WHEN 'C' THEN
CASE field
WHEN ... THEN ...
WHEN ... THEN ...
END
END

Resources