SQL exclude rows that contain anything other than desired item - sql-server

How to select rows that only contain desired items, if contain desired item and other items, exclude it.
for example, sample data,
Primarykey food_code recipes
1 22 only_rice_5874136489
2 22 only_rice_9549618454
3 33 only_rice_5874136489
4 33 only_peanut_8889548456
5 44 only_pepper_7777777715
food_code = 2 , contain the recipes begin with only_rice, that is what i want, but food_code =3 contain rice and peanut, don't select it, food_code = 44 don't select it too due to not contain rice.
Expected output;
Primarykey food_code recipes
1 22 only_rice_5874136489
2 22 only_rice_9549618454
the challenge is i have millions of rows, they all have the same string pattern, only the one set of trailing numbers are different, if write down all items that need to be excluded, e.g.(only_peanut..... only_pepper) is not a good solutions.

just check for NOT EXISTS of other item that is NOT only_rice
SELECT *
FROM recipes r
WHERE r.recipes LIKE 'only_rice%'
AND NOT EXISTS
(
SELECT *
FROM recipes x
WHERE x.food_code = r.food_code
AND x.recipes NOT LIKE 'only_rice%'
)

Related

T-SQL Get Rows With Similar Company Name Using Levenshtein

I'm using this Levenshtein function for T-SQL which works well (I'm not worried about performance). Now I want to write a query that returns all rows where the Levenshtein distance is less than x (where x might be 5 for example) using the Company name field to do the comparison.
I've tried the following, but it returns thousands of duplicate rows.
SELECT * FROM Contacts c1, Contacts c2
WHERE dbo.ufnCompareString(c1.Company, c2.Company) < 5
AND c1.id <> c2.id
I would like it to show a list like this:
1 Apple Experts
20 Apple Experts Inc.
240 H&K Paving
21 H and K Paving
98 HK Paving
189 H.K. Paving
5 J.M. Lawn Care
105 JM Lawn Care
Is it possible to do something like this? What am I doing wrong?
EDIT
I ended up with a query that looks something like this. I found that there were some "invalid" entries causing the problems I was having:
SELECT c1.ContactId, c1.Company, c1.LastName, c1.FirstName,
c2.ContactId, c2.Company, c2.LastName, c2.FirstName
FROM Contacts c1, Contacts c2
WHERE Cast(c1.ContactId AS INT) < Cast(c2.ContactId AS INT)
AND c1.Company IS NOT NULL
AND Replace(c1.Company, ' ', '') <> ''
AND c2.Company IS NOT NULL
AND Replace(c2.Company, ' ', '') <> ''
AND Len(c1.Company) > 6
AND Len(c2.Company) > 6
AND dbo.ufnCompareString(c1.Company, c2.Company) < 5
Note that the query is pretty slow running (on about 12,000 records) and I also have a different query that is more effective. The goal was to find duplicate companies that had been entered using slightly different company names and this query returned too many false positives. As to the query I actually used, it's too complicated to show here and outside the scope of this question.
To reduce the duplicates, use this instead:
SELECT * FROM Contacts c1, Contacts c2
WHERE dbo.ufnCompareString(c1.Company, c2.Company) < 5
AND c1.id < c2.id
It returns all unique pairs of contacts, whose distance is less than 5.
The query you have there should work properly, if you are getting duplicates look at the content of the Contacts table.

In SSRS, how can I add a row to aggregate all the rows that don't match a filter?

I'm working on a report that shows transactions grouped by type.
Type Total income
------- --------------
A 575
B 244
C 128
D 45
E 5
F 3
Total 1000
I only want to provide details for transaction types that represent more than 10% of the total income (i.e. A-C). I'm able to do this by applying a filter to the group:
Type Total income
------- --------------
A 575
B 244
C 128
Total 1000
What I want to display is a single row just above the total row that has a total for all the types that have been filtered out (i.e. the sum of D-F):
Type Total income
------- --------------
A 575
B 244
C 128
Other 53
Total 1000
Is this even possible? I've tried using running totals and conditionally hidden rows within the group. I've tried Iif inside Sum. Nothing quite seems to do what I need and I'm butting up against scope issues (e.g. "the value expression has a nested aggregate that specifies a dataset scope").
If anyone can give me any pointers, I'd be really grateful.
EDIT: Should have specified, but at present the dataset actually returns individual transactions:
ID Type Amount
---- ------ --------
1 A 4
2 A 2
3 B 6
4 A 5
5 B 5
The grouping is done using a row group in the tablix.
One solution is to solve that in the SQL source of your dataset instead of inside SSRS:
SELECT
CASE
WHEN CAST([Total income] AS FLOAT) / SUM([Total income]) OVER (PARTITION BY 1) >= 0.10 THEN [Type]
ELSE 'Other'
END AS [Type]
, [Total income]
FROM Source_Table
See also SQL Fiddle
Try to solve this in SQL, see SQL Fiddle.
SELECT I.*
,(
CASE
WHEN I.TotalIncome >= (SELECT Sum(I2.TotalIncome) / 10 FROM Income I2) THEN 10
ELSE 1
END
) AS TotalIncomePercent
FROM Income I
After this, create two sum groups.
SUM(TotalIncome * TotalIncomePercent) / 10
SUM(TotalIncome * TotalIncomePercent)
Second approach may be to use calculated column in SSRS. Try to create a calculated column with above case expression. If it allows you to create it, you may use it in the same way as SQL approach.
1) To show income greater than 10% use row visibility condition like
=iif(reportitems!total_income.value/10<= I.totalincome,true,false)
here reportitems!total_income.value is total of all income textbox value which will be total value of detail group.
and I.totalincome is current field value.
2)add one more row to outside of detail group to achieve other income and use expression as
= reportitems!total_income.value-sum(iif(reportitems!total_income.value/10<= I.totalincome,I.totalincome,nothing))

TSQL Least number of appearances

My question is that I want to find the "Balie" with the least number of "Maatschappijen" booked on it. So far I got this query wich displays all "Balies" and all the "Maatschappijen" with them. The wanted result is one "balienummer" record with the least number of "maatschappijen" booked on it.
Query
SELECT [Balie].[balienummer], [IncheckenBijMaatschappij].[balienummer], [IncheckenBijMaatschappij].[maatschappijcode]
FROM [Balie]
JOIN [IncheckenBijMaatschappij]
ON [Balie].[balienummer] = [IncheckenBijMaatschappij].[balienummer]
Query result
balienummer balienummer maatschappijcode
1 1 BA
1 1 TR
2 2 AF
2 2 NZ
3 3 KL
4 4 KL
LRS: https://www.dropbox.com/s/f2l9a874d5witpt/LRS_CasusGelreAirport.pdf
SELECT [Balie].[balienummer], count([IncheckenBijMaatschappij].[maatschappijcode])
FROM [Balie]
JOIN [IncheckenBijMaatschappij]
ON [Balie].[balienummer] = [IncheckenBijMaatschappij].[balienummer]
GROUP BY [Balie].[balienummer]
ORDER BY count([IncheckenBijMaatschappij].[maatschappijcode])
First record should be your answer.

Linq - Limit list to 1 row per unique values based on value (minimum) of single field

I have a stored procedure (I cannot edit) that I am calling via linq.
The stored procedure returns values (more complex but important data below):
Customer Stock Item Date Price Priority Qty
--------------------------------------------------------
CUST1 TAP 01-04-2012 £30 30 1 - 30
CUST1 TAP 05-04-2012 £33 30 1 - 30
CUST1 TAP 01-04-2012 £29 20 31 - 99
CUST1 TAP 01-04-2012 £28 10 1 - 30
I am trying to limit this list to rows which have unique Dates and unique quantities in LINQ.
I want to remove items with the HIGHER priority leaving rows with unique dates and qty's.
I have tried several group by's using Max and order by's but have not been able to get a result.
Is there any way to do this via linq?
EDIT:
Managed to convert brad-rem's answer into VB.net.
Syntax below if anyone needs it:
returnlist = (From p In returnlist
Order By p.Qty Ascending, p.Priority
Group By AllGrp = p.Date, p.Qty Into g = Group
Select g.First).ToList
How about the following. It groups by Date and Qty and orders it so that the lower priorities come first. Then, it just selects the first item from each group, which are all the lower priority items:
var result = from d in dbData
orderby d.Priority
group d by new
{
d.Date,
d.Qty
} into group1
select group1.First();

CakePHP iterate through all rows in the DB and update?

I am not sure of the cakephp way to do this. My model looks like below (simplified)
Model
id column1 column2 column3 sum
1232 3 5 2
5474 5 10 4
Now, because of the nature of the program, I need to iterate through the database, multiply each column value by a multiplier, then sum those values, then put that value into each record's sum. So, for example, if I had a variable $multiplier = 2, then I would want to have this happen for the first row:
(3*$multiplier) + (5*$multiplier) + (2*$multiplier) = 20
Model
id column1 column2 column3 sum
1232 3 5 2 20
5474 5 10 4 38
Of course, this is very simplified, but it's representative of what I want to do.
Is there a cakephp way to do this? I dont have an auto-incrementing id column in the db, but rather just an id column (which is unique).
Thank you!
Let the database do it for you:
$this->Model->updateAll(array('sum' => 'column1 + column2 + column3'));
http://book.cakephp.org/view/1031/Saving-Your-Data (see section updateAll).

Resources