SQL Server Aggregate using like - sql

I have a table with 2 columns, one is a 1/0 flag for whether they've opened an email, the second is the email address (ie joe123#domain.com).
Opened Email
0 joe123#domain.com
1 sue234#email.net
... ...
I'm trying to find if certain patterns in user names affect open rates by using regex patterns in LIKE but am unsure of the syntax for rows that match AND do NOT match the pattern.
For instance, I can do:
SELECT Email, sum(Opened)
FROM table1
WHERE Email LIKE '%joe%'
But this only gives me rows that match. I'd like rows that do and DON'T match in the same output.
I'd like to get something like this:
Pattern Opened
'joe' 55
not_joe 15987
'sue' 78
not_sue 15964
... ...
What's the best way to do this?

If you've already got a list of patterns, you can achieve the LIKE/NOT LIKE by using a CROSS JOIN (warning: performance hit).
See below for an example. Note: you can potentially improve the performance of the LIKE in the SELECT statement - there are other options available.
DECLARE #MatchList TABLE (ID INT, Pattern VARCHAR(3))
INSERT INTO #MatchList (ID, Pattern) VALUES (1, 'Joe')
INSERT INTO #MatchList (ID, Pattern) VALUES (2, 'Sue')
DECLARE #Table1 TABLE (Email VARCHAR(100))
INSERT INTO #Table1 (Email) VALUES ('joe123#domain.com')
INSERT INTO #Table1 (Email) VALUES ('sue234#email.net')
INSERT INTO #Table1 (Email) VALUES ('sue682#email.net')
INSERT INTO #Table1 (Email) VALUES ('a#domain.com')
INSERT INTO #Table1 (Email) VALUES ('b#domain.com')
INSERT INTO #Table1 (Email) VALUES ('c#domain.com')
INSERT INTO #Table1 (Email) VALUES ('d#domain.com')
INSERT INTO #Table1 (Email) VALUES ('e#domain.com')
SELECT
CASE WHEN Email LIKE '%'+Pattern+'%' THEN Pattern ELSE 'not_'+Pattern END AS Classification,
COUNT(*) Opened
FROM
#MatchList m
CROSS JOIN
#Table1
GROUP BY m.ID, CASE WHEN Email LIKE '%'+Pattern+'%' THEN Pattern ELSE 'not_'+Pattern END
ORDER BY m.ID

If i understood correctly you are trying to identify similar usernames
you can use a function like SOUNDEX to group your count by
SELECT
Email,
SOUNDEX(Email)
FROM TableA
SELECT COUNT(*) OpenedCount,
SOUNDEX(Email) EmailSOUNDEX
FROM TableA
GROUP BY SOUNDEX(Email)
ORDER BY OpenedCount desc
If all you want is something like all emails that have sue in it?
SELECT COUNT(*) OpenedCount,
SOUNDEX(Email) EmailSOUNDEX
FROM TableA
WHERE
Email like '%Sue%'
GROUP BY SOUNDEX(Email)
ORDER BY OpenedCount desc
For this kind of search maybe you can build a dictionary with relevant search terms and join it with
SELECT COUNT(*) OpenedCount,
SearchTermTable.Term
FROM TableA
JOIN SearchTermTable ON
TableA.Email like '%'+SearchTermTable.Term+'%'
WHERE
GROUP BY SearchTermTable.Term
ORDER BY OpenedCount desc

Related

Create an INSERT SQL query based on other queries

I need to perform an INSERT query like this:
INSERT INTO Clients (ClientName, CountryID) VALUES ("STYLUS", 4)
But:
Only insert if ClientName (STYLUS for the example here) does not already exists
The CountryID (4 for the example here) must be retrieved from another query: SELECT CountryID FROM Countries WHERE CountryUK = 'FRANCE'
Is it possible to build a single SQL Query for all of this ?
Thanks.
For the first condition, you need a unique index/constraint on the table:
create unique index unq_clients_clientname;
Then, you can insert the value doing:
insert into clients(clientname, countryId)
select 'STYLUS', countryid
from countries
where countryuk = 'FRANCE';
This will return an error if you attempt to insert a duplicate value. If you don't want an error, then a database-independent method is:
insert into clients(clientname, countryId)
select 'STYLUS', countryid
from countries
where countryuk = 'FRANCE' and
not exists (select 1 from clients c2 where c2.clientname = 'STYLUS');
Being Simple,
if not exists(select * from Clients where Cientname='Stylus') begin insert into Clients select 'Stylus',Countryid from Countries where countryname='France' end
will do the work.Hope It helps.

Multiple Queries into 1 Query doing counts

Ok, trying to make this make sense and see if I can do this. I have multiple queries stored in SQL Server 2012 that I can run individually to get actual results. Each of these queries connect to a multitude of tables. What I want to do is take all of these queries and put them into a single query to get counts in one master list.
So for example. I have a query that looks for all records that have no email addresses. The next query looks for all records missing a phone number in a set field. The next query looks for records missing a filled field.
Each of these queries pull back results and I can run them one at a time. I want to set myself up a single query I can run to give me counts on each in a single results list.
I started doing a Union statement and put two of the query codes into it. The results came up like this:
NoEmail NoPhone
NULL 24486
74596 NULL
What I would like this to look like is this:
NoEmail NoPhone
74596 24486
Any ideas on how to do this?
I hope this is enough info and if not, let me know and I'll get you more.
Thanks.
You can do it like this:
Set up (for demonstration purposes only, so you can see the data I'm using):
create table t1 (
id numeric,
email varchar(20)
);
insert into t1 values (1,'test#example.com');
insert into t1 (id) values (2);
insert into t1 (id) values (3);
create table t2 (
id numeric,
phone varchar(20)
);
insert into t2 values (1,'123-456-7890');
insert into t2 (id) values (2);
insert into t2 (id) values (3);
insert into t2 (id) values (4);
insert into t2 (id) values (5);
Query:
select
(select count(id) from t1 where email is null) as NoEmail,
(select count(id) from t2 where phone is null) as NoPhone;
Result:
NoEmail NoPhone
2 4
You can add as many additional queries on to the end of the query as you'd like:
select
(select count(id) from t1 where email is null) as NoEmail,
(select count(id) from t2 where phone is null) as NoPhone,
(select ...) as anotherCol,
(select ...) as yetAnotherCol;

Return value cross join

I have two tables, one is a table #1 contains user information, email, password, etc..
the other table #2 contains item information
when I do a insert into table #2, and then use the returning statement, to gather what was inserted (returning auto values as well as other information), I also need to return information from table #1.
(excuse the syntax)
example:
insert into table #1(item,user) values('this item','the user')
returning *, select * from table 2 where table #1.user = table #2.user)
in other words, after the insert I need to return the values inserted, as well as the information about the user who inserted the data.
is this possible to do?
the only thing I came up with is using a whole bunch of subquery statements in the returning clause. there has to be a better way.
I suggest a data-modifying CTE (Postgres 9.1 or later):
WITH ins AS (
INSERT INTO tbl1(item, usr)
VALUES('this item', 'the user')
RETURNING usr
)
SELECT t2.*
FROM ins
JOIN tbl2 t2 USING (usr)
Working with the column name usr instead of user, which is a reserved word.
Use a subquery.
Simple demo: http://sqlfiddle.com/#!15/bcc0d/3
insert into table2( userid, some_column )
values( 2, 'some data' )
returning
userid,
some_column,
( SELECT username FROM table1
WHERE table1.userid = table2.userid
);

Insert data in multiple tables at a time with repeated values

I have to insert data into first and second table directly. But the third table which I received data as array and inserted into 3rd table as same.
In my 3rd table values will be repeated. Ex:
values:
{name=ff,age=45,empid=23,desig=se,offid=1,details=kk,offid=2,details=aa,offid=3,details=bb,offid=4,details=cc}
So using 2nd table userid as same for all the offid, but details and other columns are different
#My issue is i will get single hit but i need to iterate for 3rd table.
with first_insert as (
insert into sample(name,age)
values(?,?)
RETURNING id
),
second_insert as (
insert into sample1(empid,desig)
values((select id from first_insert),?)
RETURNING userid
)
insert into sample2(offid,details)
values((select userid from second_insert),?)
Is this available or possible in PostgreSQL?
Yes, absolutely possible.
You can join rows from CTEs to VALUES expressions to combine them for a new INSERT in a data-modifying CTE. Something like this:
WITH first_insert AS (
INSERT INTO sample(name,age)
VALUES (?,?)
RETURNING id
)
, second_insert AS (
INSERT INTO sample1(empid, desig, colx)
SELECT i1.id, v.desig, v.colx
FROM first_insert i1
, (VALUES(?,?)) AS v(desig, colx)
RETURNING userid
)
INSERT INTO sample2(offid, details, col2, ...)
SELECT i2.userid, v.details, ...
FROM second_insert i2
, (VALUES (?,?, ...)) AS v(details, col2, ...);

Comparison Query to Compare Two SQL Server Tables [duplicate]

This question already has answers here:
sql query to return differences between two tables
(14 answers)
Closed 6 years ago.
I would like to know how to compare two different database table records. What I mean is I will compare two database tables which may have different column names but same data. But one of them may have more records than the other one so I want to see what the difference is between those two tables. To do that how to write the sql query ? FYI : these two databases are under the same SQL Server instance.
Table1
------+---------
|name |lastname|
------+---------
|John |rose |
------+---------
|Demy |Sanches |
------+---------
Table2
------+----------
|name2|lastname2|
------+----------
|John |rose |
------+----------
|Demy |Sanches |
------+----------
|Ruby |Core |
------+----------
Then when after comparing table 1 and table 2, it should return Ruby Core from Table2.
Select * from Table1
Except
Select * from Table2
It will show all mismatch records between table1 and table2
Late answer but can be useful to other readers of this thread
Beside other solutions, I can recommend SQL comparison tool called ApexSQL Data Diff.
I know you'd prefer the solution not based on the software, but for other visitors, who may want to do this in an easier way, I strongly suggest reading this article: http://solutioncenter.apexsql.com/how-to-compare-sql-server-database-tables-with-different-names/
The article explains how to use the Object mapping feature in ApexSQL Data Diff, which is particularly useful in situations where two tables share the same name, but their column names are different.
To handle such a case - each column pair needs to be mapped manually in order for the data stored within them to be included when comparing SQL database tables for differences.
If you do an outer join from T1 to T2 you can find rows in the former that are not in the latter by looking for nulls in the T2 values, similarly an outer join of T2 to T1 will give you rows in T2. Union the two together and you get the lot... something like:
SELECT 'Table1' AS TableName, name, lastname FROM
Table1 OUTER JOIN Table2 ON Table1.name = Table2.name2
AND Table1.lastname = Table2.lastname
WHERE Table2.name2 IS NULL
UNION
SELECT 'Table2' AS TableName, name2 as name, lastname2 as lastname FROM
Table2 OUTER JOIN Table1 ON Table2.name2 = Table1.name
AND Table2.lastname2 = Table1.lastname
WHERE Table1.name IS NULL
That's off the top of my head - and I'm a bit rusty :)
If you are using Sql server use a full join. it does exactly the same as Murph said but in one command.
SELECT 'Table1' AS TableName, name, lastname
FROM Table1
FULL JOIN Table2 ON Table1.name = Table2.name2
AND Table1.lastname = Table2.lastname
You could use the CHECKSUM function if you're confident that the data is expressed identically.
Example:
if not OBJECT_ID('Table1', 'Table') is null drop table Table1
if not OBJECT_ID('Table2', 'Table') is null drop table Table2
create table table1
( id int identity(0, 1),
name varchar(128),
lastname varchar(128)
)
create table table2
( id int identity(0, 1),
name varchar(128),
lastname varchar(128)
)
insert into table1 (name, lastname) values ('John', 'rose')
insert into table1 (name, lastname) values ('Demy', 'Sanches')
insert into table2 (name, lastname) values ('John', 'rose')
insert into table2 (name, lastname) values ('Demy', 'Sanches')
insert into table2 (name, lastname) values ('Ruby', 'Core')
select
table2.*
from table1
right outer join table2 on CHECKSUM(table1.name, table1.lastname) = CHECKSUM(table2.name, table2.lastname)
where table1.id is null
See the CHECKSUM MSDN topic for more information.
Try dbForge Data Compare for SQL Server. It can compare and synchronize any database data. Quick, easy, always delivering a correct result. See how it flies on your database!
create table #test
(
Sno INT IDENTITY(1,1),
ExpDate VARCHAR(50),
Amt INT,
Amt1 INT,
Amt2 INT,
SumoAmt INT
)
create table #test1
(
Sno INT IDENTITY(1,1),
ExpDate VARCHAR(50),
Amt INT,
Amt1 INT,
Amt2 INT,
SumoAmt INT
)
INSERT INTO #test(Expdate,Amt,Amt1,Amt2,SumoAmt) values ('30-07-2012',10,20,10,40)
INSERT INTO #test(Expdate,Amt,Amt1,Amt2,SumoAmt) values ('30-07-2012',10,20,20,50)
INSERT INTO #test(Expdate,Amt,Amt1,Amt2,SumoAmt) values ('30-07-2012',10,20,30,60)
INSERT INTO #test(Expdate,Amt,Amt1,Amt2,SumoAmt) values ('30-07-2012',NULL,20,40,70)
INSERT INTO #test1(Expdate,Amt,Amt1,Amt2,SumoAmt) values ('30-07-2012',10,20,10,40)
INSERT INTO #test1(Expdate,Amt,Amt1,Amt2,SumoAmt) values ('30-07-2012',10,20,20,50)
INSERT INTO #test1(Expdate,Amt,Amt1,Amt2,SumoAmt) values ('30-07-2012',10,20,30,60)
INSERT INTO #test1(Expdate,Amt,Amt1,Amt2,SumoAmt) values ('30-07-2012',NULL,20,40,70)
SELECT MIN(TableName) as TableName, Sno,Expdate,Amt,Amt1,Amt2,SumoAmt
FROM
(
SELECT '#test' as TableName,Sno,Expdate,Amt,Amt1,Amt2,SumoAmt
FROM #test
UNION ALL
SELECT '#test1' as TableName,Sno,Expdate,Amt,Amt1,Amt2,SumoAmt
FROM #test1
) tmp
GROUP BY Sno,Expdate,Amt,Amt1,Amt2,SumoAmt
HAVING COUNT(*) = 1
ORDER BY sno
If you want the differences from both the table.
(SELECT *, 'in Table1' AS Comments
FROM Table1
EXCEPT
SELECT * , 'in Table1' AS Comments
FROM Table2)
UNION
(SELECT *, 'in Table2' AS Comments
FROM Table2
EXCEPT
SELECT *, 'in Table2' AS Comments
FROM Table1)
Firefly will do exactly what you're looking for. It lets you build two sql statements then compare the results of the sql queries showing missing rows and data differences. Each query can even come from a different database like oracle / sql server.
http://download.cnet.com/Firefly-Data-Compare-Tool/3000-10254_4-10633690.html?tag=mncol