SQL Server Full-Text search - get total field value - sql

Let's say I have the following table "Addresses":
+----+-------------+---------------+------------------+
| ID | CompanyName | Street | City |
+----+-------------+---------------+------------------+
| 1 | Salvador | Hollywood 123 | Paradise City |
| 2 | Zer0 | Avenue 34 | Opportunity City |
+----+-------------+---------------+------------------+
If I make a full-text search like:
SELECT * FROM Addresses WHERE CONTAINS(*, 'Salv')
Is it possible to get back
the name of the column, which contains the founded value (in this example it would be "CompanyName")
the full value of the column, which contains the founded value (in this example it would be "Salvador"

I can suggest this:
SELECT
*,
CASE WHEN CONTAINS(CompanyName, 'Salv') THEN 'CompanyName'
WHEN CONTAINS(Street, 'Salv') THEN 'Street'
WHEN CONTAINS(City, 'Salv') THEN 'City'
END As ColumnName,
CASE WHEN CONTAINS(CompanyName, 'Salv') THEN CompanyName
WHEN CONTAINS(Street, 'Salv') THEN Street
WHEN CONTAINS(City, 'Salv') THEN City
END As FullText
FROM Addresses
WHERE CONTAINS(*, 'Salv')

Related

find duplicated record by first and last name

I have a table called beneficials. Some facts about it:
A beneficial belongs to one organization
An organization has many beneficial
Beneficials have first and last names and no other identification form.
Some sample data from the table
| id | firstname | lastname | organization_id |
|----|-----------|----------|-----------------|
| 1 | jan | kowalski | 1 |
| 2 | jan | kovalski | 3 |
| 3 | john | doe | 1 |
| 4 | jan | kowalski | 2 |
I want to find if a beneficial from an organization is also present in other organizations through first and last name and if so, I want to get the organization or organizations ids.
in the sample data above, what I want is given organization id 1, the query should return 2 because jan kowalski is also beneficial on organization 2 but not 3 because even though they match the first name, they don't match the last name
I came up with the following query:
with org_beneficials as (
select firstname, lastname from beneficials where organization_id = ? and deleted_at is null
)
select organization_id from beneficials
where firstname in (select firstname from org_beneficials)
and lastname in (select lastname from org_beneficials)
and deleted_at is null
and organization_id <> ?;
it kinda works but returns some false positive if beneficial from different organizations share the same first or last name. I need to match both first and last names and I can't figure out how.
I thought about joining the table itself but I'm not sure if this would work since an organization has many beneficials. Adding a column like fullname is not something I want to do it here
You can group by first and last names, then filter for duplicates
SELECT firstname, lastname
FROM beneficials
GROUP BY firstname, lastname
HAVING COUNT(*) > 1;
After your edits, it seems you want to select the records of people of a given organization that also appear in a different organization
SELECT *
FROM beneficials a
WHERE a.organization_id != 1
AND EXISTS (
SELECT 1
FROM beneficials b
WHERE a.firstname = b.firstname
AND a.lastname = b.lastname
AND b.organization_id = 1
);

N to N relationship using three source tables

I'm a student and I'm making a project, but I have a problem, that I cannot resolve. I've got one table with rows imported from csv file, one table with facts (GunViolences) and one with dimension (Categories - dead and injured). In the original table (imported from csv file) I've got table description, and there are long strings, which have substrings dead or injured. And now I have to connect in some way table of facts with a table of dimensions, depending on category of violence. I've created another table called ViolenceCategories to connect these tables by IDs, but I don't know how can I fill this table.
Structure:
Table FromCSV
id, date, description, address
1,12-01-2002, Shot|shotgun, address1
2,19-04-2003, injured, address2
3, 21-10-2004, shot|injured, address3
Table GunViolence
id, date, address
1, 12-01-2002, address1
2,19-04-2003, address2
3, 21-10-2004, address3
Table DimCategories
id, category
1, shot
2, injured
Table ViolenceCategories
idFact, idDim
1,1
2,2
3,2
3,1
How can I fill table VIolenceCategories?
EDIT
I've created another table to separate values of column with description
Table DimDescription
id, desc1, desc2
1, Shot, shotgun
2, injured, null
3, shot, injured
In SQL Server 2016 and newer you can use table operator STRING_SPLIT() to achieve this. That function will split a delimited string in a record into new rows for each substring. Consider:
SELECT *
FROM FromCSV
CROSS APPLY STRING_SPLIT(description, '|') AS descriptions
+----+------------+---------------------+----------+-------------+
| id | date | description | address | value |
+----+------------+---------------------+----------+-------------+
| 1 | 12-01-2002 | Shot|shotgun | address1 | Shot |
| 1 | 12-01-2002 | Shot|shotgun | address1 | shotgun |
| 2 | 19-04-2003 | three shots|injured | address2 | three shots |
| 2 | 19-04-2003 | three shots|injured | address2 | injured |
| 3 | 21-10-2004 | shot|injured | address3 | shot |
| 3 | 21-10-2004 | shot|injured | address3 | injured |
+----+------------+---------------------+----------+-------------+
SQLFiddle here
Turning this into an Insert statement to fill your ViolenceCategories table would look like:
INSERT INTO ViolenceCategories
SELECT t1.id, t2.id
FROM
(
SELECT id, value
FROM FromCSV
CROSS APPLY STRING_SPLIT(description, '|') AS descriptions
) t1
INNER JOIN DimCategories t2 ON t1.value = t2.category
SQLFiddle here

How to find only Japanese language name and English name data in a table of sql server

I have a Sql Server table loaded with data from 2 language names. Say Japanese, English.
How to identify the language and its relevant data from that table ?
How to pull only Japanese data ? i tried with this command didn't work
How to pull only English data ? i tried with firstname like '%[^!-~ ]%'
after population I need to separate Japanese and English names in 2 diff column ?
sample:
For English i tried -firstname like '%[^!-~ ]%'
For Japanese i tried -firstname like '[^A-Z]%'
select
case when firstname like '[^A-Z]%' then firstname
end as Japanese_firstname
from All_Users
Sample table
id | firstname
1 | steven
2 | 佳恵
3 | Yoshie
4 | Fruit south
5 | 果南
I need a query to produce :
is this possible to get ?
id | firstname_english | firstname_Japanese
1 | steven | null
2 | null | 佳恵
3 | Yoshie | null
4 | Fruit south | null
5 | null | 果南
One idea would be to CONVERT the values to a varchar (assuming that you aren't using a Japanese collation). If, afterwards, they contain '?', then you know that the value contains a unicode character outside of the collation and therefore can assume it has Kanji Characters in it:
SELECT ID,
CASE WHEN CONVERT(varchar(100),REPLACE(YT.FirstName,'?','')) NOT LIKE '%?%' THEN YT.FirstName END AS RomanjiName,
CASE WHEN CONVERT(varchar(100),REPLACE(YT.FirstName,'?','')) LIKE '%?%' THEN YT.FirstName END AS KanjiName
FROM (VALUES(1,N'steven'),
(2,N'佳恵'),
(3,N'Yoshie'),
(4,N'Fruit south'),
(5,N'果南'))YT(ID,FirstName);

Specify Which Column Comes First SQL

I am processing a large list of church members in order to send them a letter. We want the letter to say "Dear John & Jane Smith". We will use Word to do the mail merge from an Excel sheet. The important thing is the male name has to always come first.
Each individual has their own row in the table I am using. They have a unique ID as well as a family ID. I am using that family ID to put families together on the same row. Currently I have the male name and the female name separated using MAX(CASE WHEN) in order to specify what goes where. It looks something like this:
+-----------+------------+--------------------------+
| family id | male name | female name | last name |
+-----------+------------+--------------------------+
| 1234 | john | jane | doe |
| 1235 | bob | cindy | smith |
| 1236 | NULL | susan | jones |
| 1237 | jim | NULL | taylor |
+-----------+------------+--------------------------+
But I run into a problem when the family only has one member.
Here's a part of the query I have:
SELECT
fm.family_id AS 'Family ID',
MAX(CASE WHEN PB.gender like 'm' and FM.role_luid=29 THEN PB.nick_name END)
AS 'Male Name',
MAX(CASE WHEN PB.gender like 'f' and FM.role_luid=29 THEN PB.nick_name END)
AS 'Female Name',
PB.last_name AS 'Last Name',
FROM core_family F
I was thinking that I need to combine rows using STUFF or something like that, but I'd need some way of specifying which column comes first so that the male name always comes first. Essentially, as stated above, I need the letter to read "Dear John & Jane Smith" for families with two people and "Dear John Smith" for families with one person. So I am hoping my results might look like:
+-----------+--------------+-----------+
| family id | First name | last name |
+-----------+--------------+-----------+
| 1234 | john & jane | doe |
| 1235 | bob & cindy | smith |
| 1236 | susan | jones |
| 1237 | jim | taylor |
+-----------+--------------+-----------+
You can use your intermediate table (assuming you don't have 3 names for a family id).
From the table you indicated use:
select
id
, coalesce(male_name+' & '+female_name,male_name, female_name)
, last_name
from F;
Here is an example with your data
Basically if you concatenate using + in Sql Server you will get null. So if either male or female name is NULL, you get NULL. Coalesce will move on to the next value if it sees NULL. This way you either get a pair with '&' or a single name for each family.
I've created some test data. This technique works with the test data.
CREATE TABLE #Temp (FamID INT,
MaleName VARCHAR(20),
FemaleName VARCHAR(20),
LName VARCHAR(20))
INSERT #Temp
VALUES (1234, 'John' ,'Jane' , 'Doe' ),
(1235, 'Bob' , 'Cindy' , 'Smith'),
(1236 , NULL , 'Susan' , 'Jones'),
(1237 , 'Jim' , NULL , 'Taylor')
Here is your query.
SELECT FamID,
ISNULL(MaleName+' ','') +
CASE WHEN MaleName IS NULL OR FemaleName IS NULL THEN '' ELSE 'and ' END+
ISNULL(FemaleName,'') AS FirstName,
LName
FROM #Temp
You can use like this
SELECT
fm.family_id AS 'Family ID',
MAX(CASE WHEN PB.gender like 'm' and FM.role_luid=29 THEN PB.nick_name END)
+ '&'+
MAX(CASE WHEN PB.gender like 'f' and FM.role_luid=29 THEN PB.nick_name END)
AS 'First Name',
PB.last_name AS 'Last Name',
FROM core_family F

Splitting a string column in BigQuery

Let's say I have a table in BigQuery containing 2 columns. The first column represents a name, and the second is a delimited list of values, of arbitrary length. Example:
Name | Scores
-----+-------
Bob |10;20;20
Sue |14;12;19;90
Joe |30;15
I want to transform into columns where the first is the name, and the second is a single score value, like so:
Name,Score
Bob,10
Bob,20
Bob,20
Sue,14
Sue,12
Sue,19
Sue,90
Joe,30
Joe,15
Can this be done in BigQuery alone?
Good news everyone! BigQuery can now SPLIT()!
Look at "find all two word phrases that appear in more than one row in a dataset".
There is no current way to split() a value in BigQuery to generate multiple rows from a string, but you could use a regular expression to look for the commas and find the first value. Then run a similar query to find the 2nd value, and so on. They can all be merged into only one query, using the pattern presented in the above example (UNION through commas).
Trying to rewrite Elad Ben Akoune's answer in Standart SQL, the query becomes like this;
WITH name_score AS (
SELECT Name, split(Scores,';') AS Score
FROM (
(SELECT * FROM (SELECT 'Bob' AS Name ,'10;20;20' AS Scores))
UNION ALL
(SELECT * FROM (SELECT 'Sue' AS Name ,'14;12;19;90' AS Scores))
UNION ALL
(SELECT * FROM (SELECT 'Joe' AS Name ,'30;15' AS Scores))
))
SELECT name, score
FROM name_score
CROSS JOIN UNNEST(name_score.score) AS score;
And this outputs;
+------+-------+
| name | score |
+------+-------+
| Bob | 10 |
| Bob | 20 |
| Bob | 20 |
| Sue | 14 |
| Sue | 12 |
| Sue | 19 |
| Sue | 90 |
| Joe | 30 |
| Joe | 15 |
+------+-------+
If someone is still looking for an answer
select Name,split(Scores,';') as Score
from (
# replace the inner custome select with your source table
select *
from
(select 'Bob' as Name ,'10;20;20' as Scores),
(select 'Sue' as Name ,'14;12;19;90' as Scores),
(select 'Joe' as Name ,'30;15' as Scores)
);