How to condense a column like this? - mysql

I've tried finding something like this, but to no avail...
This is about a system of tables for a customer management system. In particular, I need to create a note history for each customer.
So, I have a table 'customers' with the columns customers.customer_ID, customers.lastname, customers.firstname, customers.postal_code, customers.city and customers.street;
and another table 'notes' with the columns notes.note_ID, notes.customer_ID, notes.subject, notes.description and notes.entered_on
Now I need to create a third table search which condenses much of the information above. It has the tables search.contact_ID, search.name, search.address and search.history. This is supposed to look like this:
contacts:
contact_ID | lastname | firstname | ...
------------+-----------+-----------+-----
1 | Doe | John | ...
2 | Dane | Jane | ...
note:
note_ID | contact_ID | subject | description | entered_on
--------+---------------+-----------------------+-----------------------+----------------
1 | 1 | call received | John Doe called us to | 2014-05-03
| | | ask for an offer |
2 | 1 | offer made | We called John Doe to | 2014-06-03
| | | submit our offer |
3 | 2 | advertisement call | We called Jane Dane to| 2014-06-03
| | | inform her of our |
| | | latest offer |
4 | 1 | offer accepted | John Doe called to | 2014-08-03
| | | accept our offer |
search:
contact_ID | name | address | history
------------+---------------+---------------------------------+-------------------
1 | Doe, John | 55 Main Street, 12345 Oldtown | 'On 2014-08-03 offer accepted: John Doe accepted our offer.
| | | On 2014-06-03 offer made: We called John Doe to submit our offer.
| | | On 2014-05-03 call received: John Doe called us to ask for an offer.'
2 | Dane, Jane | 111 Wall Street, 67890 Newtown | 'On 2014-06-03 advertisement call: We called Jane Dane to submit our offer.'
While I can deal with much of the rest, I have no idea how to generate the history information. My idea was as follows
WHILE
customers.customer_ID = note.customer_ID
AND
note.entered_on = GREATEST(note.entered_on)
DO
SET customers.note_history = CONCAT_WS(' | ', CONCAT_WS(': ',note.subject,note.description), customers.note_history);
But that one isn't necessarily chronological. Also how do I transform that into a statement compatible with the SELECT INTO used for the creation of the rest of the table?

Sounds like a case for a Group-By, along with GROUP_CONCAT
CREATE TABLE search (PRIMARY KEY(contact_ID))
SELECT contact_ID, CONCAT(lastname,', ',firstname) AS name, address,
GROUP_CONCAT(CONCAT('On ',entered_on,' ',subject,': ',description)
ORDER BY note_ID SEPARATOR "\n") AS history
FROM contacts LEFT JOIN note USING (contact_ID)
GROUP BY contact_ID
If dont want to use CREATE TABLE .. SELECT ... , can first just create (or truncate!) the table, and then use INSERT INTO ... SELECT ... instead.

Related

Return Query Results to Textbox on Userform

let me start by giving you some table structures. I have a 3 relevant tables:
OutreachEventsLog: stores information like Date/Time/Location for community events
| EventID | Date | Location |...
| 1 |2/19/2019 | Earth |
| 2 |2/18/2019 | Earth |
Staff: A list of staff employed in program
|StaffID | First Name | Last Name | Full Name |
| 1 | John | Smith | John Smith |
| 2 | Mary | Sue | Mary Sue |
| 3 | Betty | Jane | Betty Jane |
OutreachEventtoStaff: a junction table that relates staff members to the outreach events they attended.
| Event Id | Staff ID |
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
I've created a couple of forms to capture event information. The two relevant ones are called OutreachSummary and EventtoStaff. The EventtoStaff form is launched by clicking a button entitled "Add Staff" embedded in the OutreachSummary form. This process is working properly and updating all associated tables correctly.
Here's what I want to do: I want to embed a text box on the OutreachSummary form that lists all the staff members currently assigned to that event, with entries separated by a comma. Example: "John Smith, Mary Sue, Betty Jane..." where Event ID = 2
I've managed to write some code that returns a comma delimited list like the one above to a query. I then tried grab a specific row from this query based on EventID and assign it to the text box with no luck. I keep getting a ?Name error. Is there an easy way to do this? Am I even on the right track?
Thanks for the input!

Concatenate values for concatenated IDs

Database: MySQL
I have two tables, one for user's assigned roles and one that contains the role information. My problem is that the assigned roles are stored in a single field, separated by commas. I need to build a report that lists the roles by name, not the id, but still be in a single field separated by columns.
I'm thinking GROUP_CONCAT might be the solution but I've seen it used to create a concatenated list, not use one that already exists.
Table 1:USERS
ID | FNAME | LNAME | ROLE_IDS
------------------------------------------
1 | Bob | Jones | 445,44,45,449,459
2 | Mark | Doe | 426,459,445
3 | Jeff | Apple | 444,45
Table 2: ROLES
ID | ROLE_NAME
------------------------------------
4 | Basic
13 | Reporting
16 | Advanced
44 | Admin
45 | Super User
426 | Accounting
444 | User
445 | Receivables
449 | Processing
459 | Research
Expected Query Results:
ID | FNAME | LNAME | ROLES
-------------------------------------------
1 | Bob | Jones | Receivables, Admin, Super User, Processing, Research
2 | Mark | Doe | Accounting, Research, Receivables
3 | Jeff | Apple | User, Super User
For getting referencing role names, you can use GROUP_CONCAT like this :
SELECT us.ID,us.FNAME,us.LNAME,
GROUP_CONCAT(ro.ROLE_NAME) ROLES_NAME
FROM USERS us
INNER JOIN ROLES ro
ON FIND_IN_SET(ro.ID, us.ROLE_IDS) > 0
GROUP BY us.ID
I've tested it in SQLFIDDLE and working fine.

How to properly join two tables to use alternative ORDER BY

Two tables...
people (personid, name, mainordering)
entries (userid, personid, altordering)
"personid" is the common field. My app displays a draggable list users can move around. When done, they click to "lock" in their order.
Table : people
+----------+---------+--------------+
| personid | name | mainordering |
+----------+---------+--------------+
| 1 | Bob | 2 |
| 2 | Charlie | 4 |
| 3 | Jim | 1 |
| 4 | Doug | 3 |
+----------+---------+--------------+
So using mainordering, it would display:
Jim
Bob
Doug
Charlie
entries table might have (for user 16):
+--------+----------+-------------+
| userid | personid | altordering |
+--------+----------+-------------+
| 16 | 1 | 3 |
| 16 | 2 | 1 |
| 16 | 3 | 2 |
| 16 | 4 | 4 |
+--------+----------+-------------+
So if user 16 has already submitted his entry BUT NOT LOCKED IT IN, I want to display his list using altordering. i.e.
Charlie
Jim
Bob
Doug
I'm struggling with the proper join to use. Here is what I tried and isn't working (it's simply ordering by mainordering still)...
$sql = "SELECT * from entries
WHERE userid=".$_SESSION['userid']."
LEFT JOIN people ON entries.personid = people.personid
ORDER BY altordering";
Any thoughts would be much appreciated. Thank you...
Are you sure you don't get an error when using WHERE before JOIN?
It should work like this:
SELECT people.*
FROM people
JOIN entries ON entries.personid = people.personid
WHERE entries.userid={$_SESSION['userid']}
ORDER BY entries.altordering
I assume entries.personid will always have a matching person in people, so you should use an INNER JOIN. You would use FROM entries LEFT JOIN people if you wanted to retrieve altordering even for non-existing people.

Fastest way to insert data to database for one to many relationship

I am looking for a fastest way to insert data into database.
Currently I have 2 tables which is "User" and "User_Detail".
One "User" can has many "User_detail"
Example:
In database,we have the record of Age and mail for user "John".
User table
|Name |
|---------|
| John |
| Jason |
| Wilson |
User_Detail table
| Usr_Name| Property | Value |
|---------+----------+--------|
| John | Age | 12 |
| John | mail | gmail |
| Wilson | Age | 31 |
I would like to write a query to add "uni" to ALL of the users.
The result will become like this.
User_Detail table
| Usr_Name | Property | Value |
|----------+----------+--------|
| John | Age | 12 |
| John | mail | gmail |
| John | Uni | 00000 |
| Wilson | Age | 31 |
| Wilson | Uni | 00000 |
| Jason | Uni | 00000 |
Is there any suggestions or ideas on how to insert data ?
I need the fastest way to do it, as I have around 10k users in my USER table.
It can be any language or database query, as long as it can be very fast to insert the record to database.
First, consider normalizing your schema. Here is an in-depth discussion of EAV storage on dba.SE.
With your given design, this does the job:
INSERT INTO "User_Detail" ("Usr_Name", "Property", "Value")
SELECT "Name", 'Uni', '0000'
FROM "User";
In Postgres, I would also advise not to use mixed-case identifiers.
To insert a value in, just do a simple insert query.
INSERT INTO `User_detail` (`User_name`, 'Property`, `Value')
SELECT `Name`, 'H/P', 50012 FROM `Users`
To make the inserted value be something different, you need to change that hard coded value 50012 to something that resolves to the number you want there.

SQL JOIN: Just not able to understand them

Now, I know know this question related to JOIN have been asked many times. I went through many of them. But it still isn't clear to me. I read these aricles too: http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins#_comments and http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html but no, it still didn't help.
I do understand the Vein diagrams mathematically but not able to grab basic concept behind JOIN.
Suppose I have two tables.
tbl_bookdescription:
| BOOKID | BOOKNAME | BOOKREVIEW | AUTHORID |
------------------------------------------------
| 1 | SQL Basics | Cool | 1 |
| 2 | PHP Basics | Good | 2 |
| 3 | AJAX Basics | Superb | 2 |
| 4 | HTML Basics | Very Good | 3 |
tbl_authordescription
| AUTHORID | AUTHORNAME |
-------------------------
| 1 | Tom |
| 2 | Jerry |
| 3 | Phil |
I want to script a search engine for my website
So, when the user enters Tom as $searchTerm, I want the program to return the name of the book which is written by Tom. And at the same time, the user can also enter Good. This time the query should again return the name of the book. So, I thought to do something like this
SELECT bookname FROM tbl_bookdescription MATCH(bookReview) AGAINST('$searchTerm')`
and then UNION this table with SOMETHING (something which matches authorName against $searchterm).
Now, two questions:
Is this query right? Will it give me the desired results?
WHat should I write in the code in place of SOMETHING. I think I will have to JOIN both the tables(not sure). And don't know how should I join.
Help appreciated.
If you search using only one search term then your query might look like
SELECT b.*, a.*
FROM tbl_bookdescription b JOIN tbl_authordescription a
ON b.authorID = a.authorID
WHERE b.bookName LIKE '%searchterm%'
OR b.bookReview LIKE '%searchterm%'
OR a.authorName LIKE '%searchterm%'
If you replace searchterm with 'Tom' you'll get
| BOOKID | BOOKNAME | BOOKREVIEW | AUTHORID | AUTHORNAME |
------------------------------------------------------------
| 1 | SQL Basics | Cool | 1 | Tom |
Now, if it's 'Good' then
| BOOKID | BOOKNAME | BOOKREVIEW | AUTHORID | AUTHORNAME |
-------------------------------------------------------------
| 2 | PHP Basics | Good | 2 | Jerry |
| 4 | HTML Basics | Very Good | 3 | Phil |
Here is SQLFiddle demo
Try this query
SELECT
a.*
FROM
tbl_bookdescription a
INNER JOIN
tbl_authordescription b
ON
a.authorid = b.authorid
WHERE
b.authorname=''