Updating table based on the results of previous query - sql

How can I update the table based on the results of the previous query?
The original query (big thanks to GMB) can find any items in address (users table) that have a match in address (address_effect table).
From the result of this query, I want to find the count of address in the address_effect table and add it into a new column in the table “users”. For example, john doe has a match with idaho and usa in the address column so it’ll show a count of ‘2’ in the count column.
Fyi, I'm testing this on my local system with XAMPP (using MariaDB).
user table
+--------+-------------+---------------+--------------------------+--------+
| ID | firstname | lastname | address | count |
| | | | | |
+--------------------------------------------------------------------------+
| 1 | john | doe |james street, idaho, usa | |
| | | | | |
+--------------------------------------------------------------------------+
| 2 | cindy | smith |rollingwood av,lyn, canada| |
| | | | | |
+--------------------------------------------------------------------------+
| 3 | rita | chatsworth |arajo ct, alameda, cali | |
| | | | | |
+--------------------------------------------------------------------------+
| 4 | randy | plies |smith spring, lima, peru | |
| | | | | |
+--------------------------------------------------------------------------+
| 5 | Matt | gwalio |park lane, atlanta, usa | |
| | | | | |
+--------------------------------------------------------------------------+
address_effect table
+---------+----------------+
|address |effect |
+---------+----------------+
|idaho |potato, tater |
+--------------------------+
|canada |cold, tundra |
+--------------------------+
|fremont | crowded |
+--------------------------+
|peru |alpaca |
+--------------------------+
|atlanta |peach, cnn |
+--------------------------+
|usa |big, hard |
+--------+-----------------+

Use a correlated subquery which returns the number of matches:
UPDATE user u
SET u.count = (
SELECT COUNT(*)
FROM address_effect a
WHERE FIND_IN_SET(a.address, REPLACE(u.address, ', ', ','))
)
See the demo.
Results:
> ID | firstname | lastname | address | count
> -: | :-------- | :--------- | :------------------------- | ----:
> 1 | john | doe | james street, idaho, usa | 2
> 2 | cindy | smith | rollingwood av,lyn, canada | 1
> 3 | rita | chatsworth | arajo ct, alameda, cali | 0
> 4 | randy | plies | smith spring, lima, peru | 1
> 5 | Matt | gwalio | park lane, atlanta, usa | 2

Notice: I checked it in MySQL, but not in MariaDB.
The count column of users table may be able to be updated using UPDATE statement with INNER JOIN. Then you can use a query that modifies the original query to use "GROUP BY".
UPDATE users AS u
INNER JOIN
(
-- your original query modified
SELECT u.ID AS ID, count(u.ID) AS count
FROM users u
INNER JOIN address_effect a
ON FIND_IN_SET(a.address, REPLACE(u.address, ', ', ','))
GROUP BY u.ID
) AS c ON u.ID=c.ID
SET u.count=c.count;

Related

SQL query to find a partial string match that could include special characters

SQL query with special character ()
The original query (big thanks to GMB) can find any items in address (users table) that have a match in address (address_effect table).
The query works fine if address contains ',' but I can't seem to make it work if there is '()' in the address field.
Here is the sql query that's not working:
UPDATE users u
SET u.COUNT = (
SELECT COUNT(*) FROM address_effect a
WHERE FIND_IN_SET(a.address, REPLACE(u.address, ', ', ','')'))
)
Fyi, I'm testing this on my local system with XAMPP (using MariaDB).
I tried to identify '()' as an escape character by prepending it with backslash '' but it doesn't help.
user table
+--------+-------------+---------------+--------------------------+--------+
| ID | firstname | lastname | address | count |
| | | | | |
+--------------------------------------------------------------------------+
| 1 | john | doe |james street, idaho, usa | |
| | | | | |
+--------------------------------------------------------------------------+
| 2 | cindy | smith |rollingwood av,lyn, canada| |
| | | | | |
+--------------------------------------------------------------------------+
| 3 | rita | chatsworth |arajo ct, alameda, cali | |
| | | | | |
+--------------------------------------------------------------------------+
| 4 | randy | plies |smith spring, lima, (peru)| |
| | | | | |
+--------------------------------------------------------------------------+
| 5 | Matt | gwalio |park lane, (atlanta), usa | |
| | | | | |
+--------------------------------------------------------------------------+
address_effect table
+---------+----------------+
|address |effect |
+---------+----------------+
|idaho |potato, tater |
+--------------------------+
|canada |cold, tundra |
+--------------------------+
|fremont | crowded |
+--------------------------+
|peru |alpaca |
+--------------------------+
|atlanta |peach, cnn |
+--------------------------+
|usa |big, hard |
+--------+-----------------+
I would suggest using regular expressions for this. It seems more general than fiddling with the string:
update users u
set count = (select count(*)
from address_effect ae
where u.address regexp concat('[[:<:]]', ae.address, '[[:>:]]'))
);
The funky character class is MySQL's way of delineating a word boundary (I am more used to \W but MySQL doesn't support that).
Here is a db<>fiddle.
Just like you replace the space after each comma with just a comma, use REPLACE() to remove the chars '(' and ')':
FIND_IN_SET(a.address, REPLACE(REPLACE(REPLACE(u.address, ', ', ','), '(', ''), ')', ''))
See the demo.
Results:
| ID | firstname | lastname | address | count |
| --- | --------- | ---------- | -------------------------- | ----- |
| 1 | john | doe | james street, idaho, usa | 2 |
| 2 | cindy | smith | rollingwood av,lyn, canada | 1 |
| 3 | rita | chatsworth | arajo ct, alameda, cali | 0 |
| 4 | randy | plies | smith spring, lima, (peru) | 1 |
| 5 | Matt | gwalio | park lane, (atlanta), usa | 2 |

SQL, query to check and list distinct entries that occur in another table within a specific time frame

I'm using Oracle.
I have two tables. One contains users and the other is an access log of sorts. I need to list all users whose latest log entry appears in the log within a specified time frame including the timestamp of the latest entry. A single user can have several entries in the log.
Here are simplified versions of the tables:
Users
|----------------------------------|
| userid| username | name |
|----------------------------------|
| 1 | josm | John Smith |
| 2 | lajo | Laura Jones |
| 3 | miwi | Mike Williams |
| 4 | subo | Susan Brown |
| 5 | peda | Peter Davis |
| 6 | jami | Jane Miller |
|----------------------------------|
Log
|----------------------------------|
| userid| action | timestamp |
|----------------------------------|
| 3 | a | 20-01-2020 |
| 2 | v | 19-11-2019 |
| 2 | y | 02-11-2019 |
| 4 | b | 15-09-2019 |
| 1 | a | 23-05-2019 |
| 6 | y | 22-05-2019 |
| 3 | b | 16-04-2019 |
| 2 | a | 07-01-2019 |
| 5 | v | 18-11-2018 |
| 6 | a | 12-09-2018 |
|----------------------------------|
Desired result if the time frame is set to last six months:
|---------------------------------------|
| username | name | timestamp |
|--------------------------|------------|
| miwi | Mike Williams | 20-01-2020 |
| lajo | Laura Jones | 19-11-2019 |
| subo | Susan Brown | 15-09-2019 |
|---------------------------------------|
Any help will be greatly appreciated.
You can use aggregation:
select u.username, u.userid, max(l.timestamp)
from logs l join
users u
on l.userid = u.userid
group by u.username, u.userid
having max(l.timestamp) >= add_months(sysdate, -6)

Compare very different tables

I have two Tables that are read from separate files (.xlsx and .csv) and are imported into MS Access. They are not in the same format
(which is why I'm having such a difficult time with it).
Here is xlsxTable:
+--------------------------------------------------------------------------------------+
| ID | Name | SSN | SSN2 | Address |
+--------------------------------------------------------------------------------------+
| 00012345 | Robert Robin | ThisIsSSN | ThisIsSSN2 | 12345 StreetName St. CityName, KS |
| 00013245 | Pete Peters | ThisIsSSN | ThisIsSSN2 | 54321 StreetName St. CityName, MO |
| 00012358 | Mike Michaels| ThisIsSSN | ThisIsSSN2 | 69874 StreetName St. CityName, NY |
| 00098755 | Tim Timpson | ThisIsSSN | ThisIsSSN2 | 15987 StreetName St. CityName, KY |
| 00035784 | Tom Thompson | ThisIsSSN | ThisIsSSN2 | 95123 StreetName St. CityName, CA |
| 00012584 | Will Willers | ThisIsSSN | ThisIsSSN2 | 35789 StreetName St. CityName, WA |
| ........ | ........... | ......... | .......... | ................................. |
Here is my csvTable:
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tracking_number | last_name | first_name | middle_name | suffix | alias_last_name | alias_first_name | alias_middle_name | alias_suffix | number | number_type | dob | street | city | state | zip | country | phone |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 135247 | Keeves | Michael | | Jr | | | | | ThisIsSSN | SSN/ITIN | 1/1/1990 | StreetName | CityName | NJ | | US | |
| 135248 | Jackson | Sue | Master | | | | | | ThisIsSSN | SSN/ITIN | 10/29/1980 | StreetName | CityName | NY | zip | US | |
| 135248 | Thomspon | Dolf | Laundry | | | | | | DriverNum | Driver'sLicense | 11/15/1962 | StreetName | CityName | KS | | US | |
| 135249 | Peters | Pete | | | Peters | Petey | | | ThisIsSSN | SSN/ITIN | 5/6/1975 | StreetName | CityName | PA | zip | US | |
| 135250 | Rogers | Steve | | | | | | | ThisIsSSN | SSN/ITIN | 12/25/1990 | StreetName | CityName | CT | zip | US | |
| 135250 | Nikolson | Jack | | Jr | | | | | DriverNum | Driver'sLicense | 8/5/1975 | StreetName | CityName | CA | zip | US | |
| 135251 | Keeves | Keanu | Neo | | | | | | ThisIsSSN | SSN/ITIN | 10/30/2000 | StreetName | CityName | TX | zip | US | |
| 135252 | Starch | Tony | | | | | | | ThisIsSSN | SSN/ITIN | 9/10/1975 | StreetName | CityName | NJ | | US | |
|...................|...............|................|...............|..........|...................|......................|........................|.................|.............|....................|............|.............|..............|.........|......|.........|.......|
| dba_name | number | number_type | incorporated | street | city | state | zip | country | phone | | | | | | | | |
| Mini Mart | 92585487 | EIN | | Street | CityName | state | zipNum | GT | | | | | | | | | |
| | 15987548 | EIN | | street | CityName | KS | zipNum | US | | | | | | | | | |
| Check Systems | 35854855 | EIN | | street | CityName | CA | zipNum | US | | | | | | | | | |
|...................|...............|................|...............|..........|...................|......................|........................|.................|.............|....................|............|.............|..............|.........|......|.........|.......|
Where dba_name is in the above table is an actual row. For some reason, there's another portion of the file that starts a new list.
I have to query these tables and if a name along with SSN match, then I must take the name, address and SSN, and do something with them (most likely put into another table for export). I have loaded both tables from the files necessary.
I'm now needing to iterate through and find the matches. For the sake of the sample data, Pete Peters should match here since the data is in both tables. My expected output should look a lot like the first table:
| ID | Name | SSN | SSN2 | Address |
I currently have an MS Access database that contains these tables. Though, with how the data is parsed, I'm not sure where to even start with the SQL. Performance-wise, this may be extensive. I'm just looking for a way to get it working first.
How can I query these two very different tables and only pull the data that matches?
Access has a find duplicates query wizard. The fastest way to handle the problem is to combine the tables manually or using 1 or more queries and then run the wizard. Again, get all your data into one table and then run the wizard. To make things complicated by breaking them down.
you might get the data from the CSV Table: with a query like:
SELECT csvTable.First_Name AS First_Name, csvTable.Last_Name AS Last_Name, csvTable.Number AS [Number]
FROM csvTable
GROUP BY csvTable.First_Name, csvTable.Last_Name, csvTable.Number
HAVING (((Count(csvTable.Number))>1));
then create a query with the same structure from the xlsx table:
SELECT Left([xlsxTable]![FullName],InStr([xlsxTable]![FullName]," ")) AS First_Name, Right([xlsxTable].[FullName],Len([xlsxTable].[FullName])-InStr([xlsxTable]![FullName]," ")) AS Last_Name, xlsxTable.SSN AS [Number]
FROM xlsxTable
GROUP BY Left([xlsxTable]![FullName],InStr([xlsxTable]![FullName]," ")), Right([xlsxTable].[FullName],Len([xlsxTable].[FullName])-InStr([xlsxTable]![FullName]," ")), xlsxTable.SSN
HAVING (((Count(xlsxTable.SSN))>1));
The having Count >1 does the work of finding the duplicates. Most of the rest of this is obtuse string manipulations to turn Full Name into first and last name directly in the sql. Then combine the queries so you can run them at the same time in the sql pane using a UNION ALL statement:
SELECT csvTable.First_Name AS First_Name, csvTable.Last_Name AS Last_Name, csvTable.Number AS [Number]
FROM csvTable
GROUP BY csvTable.First_Name, csvTable.Last_Name, csvTable.Number
UNION ALL
SELECT Left([xlsxTable]![FullName],InStr([xlsxTable]![FullName]," ")) AS First_Name, Right([xlsxTable].[FullName],Len([xlsxTable].[FullName])-InStr([xlsxTable]![FullName]," ")) AS Last_Name, xlsxTable.SSN AS [Number]
FROM xlsxTable
GROUP BY Left([xlsxTable]![FullName],InStr([xlsxTable]![FullName]," ")), Right([xlsxTable].[FullName],Len([xlsxTable].[FullName])-InStr([xlsxTable]![FullName]," ")), xlsxTable.SSN;
union all keeps duplicates while union omits them. I have removed the having statements from the union as I find it works better. next use the find duplicates wizard on your combined query like:
SELECT [combine tables].First_Name, [combine tables].Last_Name, [combine tables].Number
FROM [combine tables]
GROUP BY [combine tables].First_Name, [combine tables].Last_Name, [combine tables].Number
HAVING (((Count([combine tables].Number))>1));

What SQL query should I perform to get the result set as I expected?

I'm having problem to get the result I need :/ these are my tablets. On Postgresql
table: logins table: users
+------------------------+ +------------------+
| iduser | date | | iduser | name |
|------------------------| |------------------|
| 1 |'2017-06-06'| | 1 | Joe |
|------------------------| |------------------|
| 1 |'2017-06-06'| | 2 | Jane |
|------------------------| |------------------|
| 2 |'2017-06-07'| | 3 | Mary |
|------------------------| +------------------+
| 3 |'2017-06-07'|
|------------------------|
| 3 |'2017-06-07'|
|------------------------|
| 3 |'2017-06-07'|
+------------------------+
Im Using this query:
SELECT name, date, count(*) FROM logins l
LEFT JOIN users u
ON u.iduser= l.iduser
GROUP BY
u.name,l.date
ORDER BY
l.date
This it what I got:
+-----------------------------------+
| name | date | count |
|-----------------------------------|
| Joe | '2017-06-06' | 2 |
|-----------------------------------|
| Jane | '2017-06-07' | 1 |
|-----------------------------------|
| Mary | '2017-06-07' | 3 |
+-----------------------------------+
but what I really need to get from the result its this:
+-----------------------------------+
| name | date | count |
|-----------------------------------|
| Joe | '2017-06-06' | 2 |
|-----------------------------------|
| Jane | '2017-06-06' | 0 |
|-----------------------------------|
| Mary | '2017-06-06' | 0 |
|-----------------------------------|
| Joe | '2017-06-07' | 0 |
|-----------------------------------|
| Jane | '2017-06-07' | 1 |
|-----------------------------------|
| Mary | '2017-06-07' | 3 |
+-----------------------------------+
What should I do? please help!!! thanks a lot! ^^
In SQL Server & Postgres:
Getting all combinations of date and users, then left join to login:
select
d.date
, u.name
, count(l.iduser) as login_count
from (select distinct date from logins) d
cross join users u
left join logins l
on l.iduser=u.iduser
and l.date=d.date
group by d.date, u.name
rextester demo (sql server): http://rextester.com/THJE85313
rextester demo (postgres): http://rextester.com/BNHE97192
returns:
+---------------------+------+-------------+
| date | name | login_count |
+---------------------+------+-------------+
| 2017-06-06 00:00:00 | Jane | 0 |
| 2017-06-07 00:00:00 | Jane | 1 |
| 2017-06-06 00:00:00 | Joe | 2 |
| 2017-06-07 00:00:00 | Joe | 0 |
| 2017-06-06 00:00:00 | Mary | 0 |
| 2017-06-07 00:00:00 | Mary | 3 |
+---------------------+------+-------------+

How do I add a "total_num" field by aggregating equal values with SQL?

Well, I apologize for the horrible question title. I am not a SQL or database guy so I find I am somewhat lacking the vocabulary to succinctly describe what I am trying to do. So, I will just pose the question as an anecdote.
I have two tables:
+-------+--------+------------+
| STATE | REGION | CAPITAL |
+-------+--------+------------+
| WA | X | Olympia |
| CA | IX | Sacramento |
| TX | VI | Austin |
+-------+--------+------------+
And:
+-------+--------+-------+
| NAME | NUMBER | STATE |
+-------+--------+-------+
| Tom | 1 | WA |
| Dick | 5 | WA |
| Larry | 45 | WA |
| Joe | 65 | TX |
| John | 3 | CA |
+-------+--------+-------+
How can I then query the second table so that I can "append" a fourth field to the first table that stores a total count for the number of people in that state, such that the first table would then look like this:
+-------+--------+------------+-------+
| STATE | REGION | CAPITAL | COUNT |
+-------+--------+------------+-------+
| WA | X | Olympia | 3 |
| CA | IX | Sacramento | 1 |
| TX | VI | Austin | 1 |
+-------+--------+------------+-------+
Thanks in advance.
SELECT s.STATE, s.REGION, s.CAPITAL, COUNT(*) as 'COUNT'
FROM secondtable s
JOIN firsttable f ON s.STATE = f.STATE
GROUP BY f.STATE, f.REGION, f.CAPITAL
ORDER BY COUNT(*) DESC
Try this
select sc.state,sc.region.sc.capital, count(*) as tot
from State_City_Table sc
join people_table pt on pt.state=sc.state
group by sc.state,sc.region.sc.capital