SQL saviong outputs to seperate files - sql

I have a table like this:
CREATE TABLE Persons (
PersonID int,
LastName varchar(255)
);
The Ouput:
**Person ID | Last Name**
100 | Jones
105 | Davids
109 | Jones Jr
110 | Jones Jr Jr
Is it possible that SQL can put the data in sperate CSV files? In this case 2 csv File which contains
CSV File1:
**Person ID | Last Name**
105 | Davids
and in the other csv 2 file:
**Person ID | Last Name**
100 | Jones
109 | Jones Jr
110 | Jones Jr Jr

If you are using SQL SERVER
$AttachmentPath = "CV File location"
$QueryFmt= "Query"
Invoke-Sqlcmd -ServerInstance Server -Database DBName -Query $QueryFmt | Export-CSV $AttachmentPath
If you are using Oracle 12, you can simply type
set markup csv on;
spool C:\DBA\test\file1.csv;
Select * from persons where name like 'David';
spool C:\DBA\test\File2.csv;
Select * from persons where name not like 'David';
Another way is to write a procedure and execute this procedure.

Related

Similarity search for name surname

I have a column name which contains name surname (name space surname) and I would like to search it based on
name, surname but I would like to match cases where people accidentally inserted surname name in a different order
misspelled names surnames by 1-2 characters.
You should read about the pg_trgm extension and its function similarity(). A few examples below.
Example data:
create table my_table(id serial primary key, name text);
insert into my_table (name) values
('John Wilcock'),
('Henry Brown'),
('Jerry Newcombe');
create extension if not exists pg_trgm; -- install the extension
Example 1:
select *,
similarity(name, 'john wilcock') as "john wilcock",
similarity(name, 'wilcock john') as "wilcock john"
from my_table;
id | name | john wilcock | wilcock john
----+----------------+--------------+--------------
1 | John Wilcock | 1 | 1
2 | Henry Brown | 0 | 0
3 | Jerry Newcombe | 0.037037 | 0.037037
(3 rows)
Example 2:
select *,
similarity(name, 'henry brwn') as "henry brwn",
similarity(name, 'brovn henry') as "brovn henry"
from my_table;
id | name | henry brwn | brovn henry
----+----------------+------------+-------------
1 | John Wilcock | 0 | 0
2 | Henry Brown | 0.642857 | 0.6
3 | Jerry Newcombe | 0.04 | 0.0384615
(3 rows)
Example 3:
select *
from my_table
where similarity(name, 'J Newcombe') >= 0.6;
id | name
----+----------------
3 | Jerry Newcombe
(1 row)
To counter the exchanged parts of the name you could use split_part() to split the name in its two parts and compare both of them, something similar to the following:
SELECT *
FROM person
WHERE split_part(name, ' ', 1) IN ('<given_name_searched_for>'
'<surname_searched_for>')
OR split_part(name, ' ', 2) IN ('<given_name_searched_for>'
'<surname_searched_for>');
Or have a look at the other string functions and operators. -- there a variants of split functions using regular expressions, e.g..
Are there names like 'John F. Kennedy', that is, with more than one token? Are there names with more than one contiguous spaces? Bear in mind that these have to be addressed with further means if any. (Such things can get hairy. If possible consider revising your design and use a separate column for the surname.)
For the similarity part: PostgreSQL provides some modules, that might be useful here:
fuzzystrmatch
pg_trm

Concat multiple rows PSQL

id | name | Subject | Lectured_Times | Faculty
3258132 | Chris Smith | SATS1364 | 10 | Science
3258132 | Chris Smith | ECTS4605 | 9 | Engineering
How would I go about creating the following
3258132 Chris Smith SATS1364, 10, Science + ECTS4605, 9,Engineering
where the + is just a new line. Notice how after the '+'(new line) it doesnt concat the id,name
try
SELECT distinct concat(id,"name",string_agg(concat(subject, Lectured_Times , Faculty), chr(10)))
from tn
where id = 3258132
group by id;
As mentioned above string_agg is perfect solution for this.
select
id, name, string_agg(concat(subject, Lectured_Times, Faculty), '\n')
from table
group by id, name

SQL delete where column = *

How can I delete from database where column is no matter?
For example I have that table
Table people:
name | age |
------+-----+
James | 20 |
Smith | 25 |
James | 40 |
I want to do this:
delete from people
where name = 'James'
and age = *;
I know that I can do:
delete from people
where name = 'James'
But I do not need this
Try:
DELETE FROM people where
name like '%personsname%'
If you are refering to a parameter that can be NULL then use it like this
delete from people
where name = #nameParam
and (#ageParam is null or age = #ageParam)

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

How to generate SQL output with pipes with multiple tables

I am using SQL Server.
I have a table of students like this:
StudentID TeacherNumber
123 1
124 1
125 2
126 2
127 1
128 3
I also have a table of teachers like this:
TeacherNumber TeacherName
1 Adams
2 Johnson
3 Marks
I need to have output that looks like this:
TeacherNumber Teacher Students
1 Adams 123|124|127
2 Johnson 125|126
3 Marks 128
I appreciate your help. Thank you.
I posted a similar question previously, and got a response that worked here:
How to generate sql output as piped
Now that I added another table I am having trouble. I appreciate the help.
Fiddle:
http://sqlfiddle.com/#!6/27600/29/0
Query:
select distinct st1.teachernumber,
teachername as teacher,
stuff(( select '|' + cast(st2.studentid as varchar(20))
from students st2
where st1.teachernumber = st2.teachernumber
order by st2.studentid
for xml path('')
),1,1,'') as students
from students st1
join teachers t
on st1.teachernumber = t.teachernumber
The reason I had to convert STUDENTID to VARCHAR is because by adding the pipe character that data type would no longer be valid and you'd get an error. You have to cast it as varchar to get the pipe delimiter to work with an integer field (I assume STUDENTID is an INT field).
Output:
| TEACHERNUMBER | TEACHER | STUDENTS |
|---------------|---------|-------------|
| 1 | Adams | 123|124|127 |
| 2 | Johnson | 125|126 |
| 3 | Marks | 128 |