UPDATE all empty array columns to be NULL - mysql

MySQL query is:
UPDATE buddy SET buddy_positions = CONCAT('| ',
(IF(buddy1_request = 'Yes', 'buddy1_main | ','')),
(IF(buddy2_request = 'Yes','buddy2_main | ','')),
(IF(buddy3_request = 'Yes','buddy3_main | ','')),
(IF(buddy4_request = 'Yes' NULL,'buddy4_main | ','')),
(IF(buddy5_request = 'Yes','buddy5_main | ','')))
My problem is that if buddy1_request = 'Yes' I want it to CONCAT the data in a separate cell (buddy1_main) plus some extra bits. I'm struggling to output the result from another column however, I can type it in manually but can't find a way to do this automatically.
EDIT
So my data looks like this:
|buddy1_request | buddy1_main | buddy2_request | buddy2_main |buddy_position|
|---------------|-------------|----------------|-------------|--------------|
|Yes |prop |no |NULL |(CONCAT HERE) |
So what I want to happen is that if buddy1_request says 'Yes' then it includes the contents of buddy1_main in the CONCAT for buddy_position and so on
In this example the output would simpley be "prop", however if buddy2_request said "Yes" it would have a value such as "winger" and the CONCAT would return "prop","winger"
My problem is that my current query returns the text "buddy1_main","buddy2_main"
I don't know how to reference the column and pull the value through in the CONCAT.
PS I don't see how this is bad design, it's a table where player adds a friend and if they click yes to playing with them that week it brings through their position as well into buddy1_main, I then need a way of outputting all the results into a table for clubs to view so they know that player also comes with X amount of people that can platy positions X,Y and Z.
However if player 2 is unavailable but player 4 is available it needs to ignore player 2's position. I hope that makes sense, there's a lot of reasons it's done this way and it's actually a very complex system when you drill down into it all. I've kept it this way so it's modular and not linear as a model so I can change aspects to it as needed without having a knock on effect. I'm not concerned about how memory hungry it is on the server at this stage.

Related

How to find missing numbers within a column of strings

I'm trying to find unaccounted for numbers within a substantially large SQL dataset and facing some difficulty sorting.
By default the data for column reads
'Brochure1: Brochure2: Brochure3:...Brochure(k-1): Brochure(k):'
where k stands in for the number of brochures a unique id is eligible for.
Now the issue arises as the brochures are accounted for a sample updated data would read
'Brochure1: 00001 Brochure2: 00002 Brochure3: 00003....'
How does one query out the missing numbers, if in the range of number of say 00001-88888 some haven't been accounted next to Brochure(X):
The right way:
You should change the structure of your database. If you care about performance, you should follow the good practices of relational databases, so as first comment under your question said: normalize. Instead of placing information about brochures in one column of the table, it's much faster and more clear solution to create another table, that will describe relations between brochures and your-first-table-name
<your-first-table-name>_id | brochure_id
----------------------------+---------------
1 | 00002
1 | 00038
1 | 00281
2 | 28192
2 | 00293
... | ...
Not mention, if possible - you should treat brochure_id as integer, so using 12 instead of 0012.
The difference here is, that now you can make efficient and simple queries, to find out how many brochures one ID from your first table has, or what ID any brochure belongs to. If for some reason you need to keep the ordinal number of every single brochure you can add a column to the above table, like brochure_number.
What you want to achieve (not recommended): I think the fastest way to achieve your objective without changing the db structure, is to get the value of your brochures column, and then process it with your script. You really don't want to create a SQL statement to parse this kind of data. In PHP that wolud look something like this:
// Let's assume you already have your `brochures` column value in variable $brochures
$bs = str_replace(": ", ":", $brochures);
$bs = explode(" ", $bs);
$brochures = array();
foreach($bs as $b)
$brochures[substr($b, 8, 1)] = substr($b, strpos($b, ":")+1, 5);
// Now you have $brochures array with keys representing the brochure number,
// and values representing the ID of brochure.
if(isset($brochures['3'])){
// that row has a defined Brochure3
}else{
// ...
}

How to loop transpose function for every row containing a specific character on Google Sheets?

This is what I have (each "|" symbol indicates a new column on the same row)
John | Doe
Manager
NY
123-45-67
Fax: 987-54-32
a#b
Jane
Assistant
CA
234-56-78
c#d
Mike | Brown
Analyst | Intern
CA
345-67-89
e#f
However, I am trying to get it to look like the below on Google Sheets:
John Doe | Manager | [empty] | NY | 123-45-67 | Fax: 987-54-32 | a#b
Jane | Assistant | [empty] | CA | 234-56-78 | [empty] | c#d
Mike Brown | Analyst | Intern | CA | 345-67-89 | [empty] | e#f
The names are all formatted in bold font so I can use that property as my identifier to be able to merge last names and first names into the same column. However, not sure how I can leave a column empty if a fax number exists in one record and it doesn't in another.
I ultimately want it to be able to create a new record row after each cell that has a "#" character in it. How much of this is possible? If it can be done, how much of it can be done and how can it be done in Google Sheets?
It took some work, but this can be done without a script, through use of built in functions in the sheet. I will put a link to an example below in a comment, but I cannot promise to keep it there forever. But here is the method.
STEP 0: Add appropriate headers in row 1 for sanity. Reserve column A for a record locator, to be built later. Thus, in the example above "John" sits in B2 and "Doe" is in C2.
STEP 1: Build a column for each type of field, and indicate whether the value is that type. For instance, my column D determines if something is an email with the (draggable) formula =iferror(find("#",B2)>0,false). In column E I determine if something is a name. You could use the bolding idea, but I went for =or((row()=2),D1), which says either I am the first row of data, or the preceding row was an email. This too gets dragged. Similarly to test for states: =and((LEN(B2)=2),(B2=upper(B2))), fax =(upper(mid(B2,1,3))="FAX"), ID =and((len(B2)=9),mid(B2,4,1)="-",mid(B2,7,1)="-"), and finally anything else must be a job =not(or(D2,E2,F2,G2,H2)).
STEP 2: Construct the value from the 2 potential columns. If the second is empty, just the first. Otherwise names get a space between and anything else gets "and" between. =if(ISBLANK(C2),B2,if(E2,B2&" "&C2,B2&" and "&C2))
STEP 3: Construct the record type based on which things were true. I put the type names in the header row, so they will match later, which makes this formula a bit impenetrable, but I hope you get the idea: =if(D2,$S$1,if(E2,$N$1,if(F2,$P$1,if(G2,$R$1,if(H2,$Q$1,if(I2,$O$1,"error")))))). Now in A2 I append the record number to the job type, where the record number is how many names we have met so far, thus (also draggable) =K2&countif($E$2:$E2,true). [The idea of building a key this way comes from Prashanth
STEP 4: I left column L blank for neatness so the results are separate from the input and calculations, and then I put a record number in column M as follows =(row()-1). And now we apply vlookup across the rest of the row to get each field by matching it to the column header of the desired output (name|job|state|ID|fax|email) as follows =vlookup(N$1&$M2,$A:$K,10,false), which is built to be draggable both to the rightmost column (email) and the bottom row (row 4 for record 3, in our example). Missing data show up as #N/A (if you find that ugly, an IfError can make it say something nicer).
I hope this illustrates not only a result, but also a method, with which you could tinker if you saw fit.

MySQL table structure suggestions?

Hey i'm currently working on a database project and simply can't think of a good way to save my data. The data being saved changes depending on what is being saved.
My current not-so-good table is:
User-ID | XLoc | YLoc | ZLoc | Data-ID | Data (String)
The data column is currently being saved as a string (serialized depending on object being saved) then unserialized. I understand serialization is a dumb idea when it comes to a proper database, but i haven't a clue on how else i could've done this.
I was thinking about assigning "sub" tables depending on the Data-ID then joining all the tables together on a search but i feel that wont be very efficient.
So my idea would play out like:
User-ID | XLoc | YLoc | ZLoc | Data-ID | Data-Index
Data-Index | SomeObjectRelatingData | SomeObjectRelatingData
Once again i just don't know how i'd put this all together so any help at all would be EXTREMELY helpful and i'm sorry if i was vague.
Example Data:
Particle-Name(string) | Material (int)
Time(long) | MeshType (int)
This data is currently serialized like so: Time:MeshType in string format. Once the data is retrieved from the database it's deserialized then changed back into it's formal type;
All the data needs to be accessed easily and they all share the User-ID, XLoc, YLoc, ZLoc.

Creating SQL Table layout for dynamic document

I apologize if this question is vague, but I'll try to be as clear as possible. I've been given a task where I'm to take a text file, store its content in SQL Server 2008, and automate the creation of a form letter given certain inputs. I've been able to break it into the following generic structure (pay no attention to the content, it's just generic text, but the situational break-down is similar):
Welcome [User],
[if #purchase = true, add this paragraph]
Thank you for purchasing the [device / subscription / subscription and device]
from this business on [date].
[#purchase = true and #return = true, add this paragraph]
I'm sorry you returned it!
...
Signed,
[Author]
[Author Image]
Assuming I'm already able to bring in all the necessary variables (user, purchase, return, date, device or device and subscription or subscription only), how should I go about storing the letter pieces in SQL? would it be considered fine to have a structure like the following:
+-------+-----------------+----------+--------+
| Order | Text | purchase | return |
+-------+-----------------+----------+--------+
| 1 | (1st paragraph) | TRUE | null |
| 2 | (2nd paragraph) | TRUE | FALSE |
+-------+-----------------+----------+--------+
Where I store the contents of the first paragraph as:
Thank you for purchasing the [device / subscription / subscription and device]
from this business on [date].
And then write a stored procedure to piece it together based on the Boolean columns, and find/Replace the bracketed bits with input variables to output the entire letter as a string? It doesn't seem like it would be able to handle much variability, to be honest. Maybe breaking down the document into paragraph and sentence tables?
My ultimate goal would be to output this to either a report I create or, perhaps more ideally, to a Word document (though this is probably a whole different bit of research). Am I way off base here? Any insight is helpful.
you can use replace in select statment
for example
SELECT replace(replace(Text, 'device', #deviceVaribale), 'subscription', #subscriptionVaribale) FROM Order

Hard-coding URLs vs Nested Set vs Combo in Content System

I've been putting together a database to handle content produced for a site, however, thinking about the long-term, I'm unsure if I have the best system.
At present I'm using the routing method of passing everything via index.php which .htaccess routes as follows index.php?route=example/url (user sees http://www.domain.com/example/url)
At present the database is setup like below:
uid | title | content | category
--------------------------------------------------
/ | Home | aaa | 1
/example | Example | bbb | 2
/example/url | Example: URL | ccc | 2
Though I am not sure if this is the best approach, especially if I wanted to rename example to something - I'd have to rename each URL...
So I've also thought about the Nested Set method (such as http://www.phpclasses.org/package/2547-PHP-Manipulate-database-records-in-hierarchical-trees.html) though this would just show lots of different numbers in the database where I could access everything by it's node. Example below;
node | left | right | name
--------------------------
1 | 1 | 6 | Home
2 | 2 | 5 | Example
3 | 3 | 4 | URL
Then I could use the node as the uid? But I'm unsure how I could translate http://www.domain.com/example/url to the uid equalling 3...
I already do have a category column in my database at the moment, to categorise the content, though I could potentially alter this.
I'm basically looking for suggestions about how to proceed, because as the site gets more content it will be harder to change the setup - so I want to ideally get this right from day one.
Which of the two is better for scalability?
If the second, how to translate the URL to the node?
Could I somehow combine both so that the original database stores the uid as the node number, then do a join of some sort to make the uid be a url (as in 1) - then ]
^ I think I'd prefer this (the third), but unsure how to do in MySQL exactly, with some other benefits:
I could replace my category system with the parent node - which may be better
I could also then in theory store the node ID within a stats system, rather than a URL
If anyone can give some help/suggestions - I'd be grateful!
Well, if you use index.php?route=example/url, you could always do something like this:
$args = explode( '/', $_GET['route'] );
$args = filter_var_array( $_GET['route'], FILTER_SANITIZE_STRING );
Then your values of $args would be:
0 -> example
1 -> url
etc. You could then use these values to determine what template to load, and what content to grab from the database, or whatever else you're doing already.
HTH.
The nested set model probably is a good choice here. That'd result in a table layout like (id,left,right are the fields required by the nested set model, the others contain the respective content):
| id | left | right | uid | title | content | category |
More details on how to perform a particular query can be found here.
However I would not perform the look up on the database but a simple array cache:
new array('/' => array('content' => 'aaa', 'category' => 'bbbb'),
'/example/' => array(),
.....
);
This cache can be build up very easy (though expensive) and queried very easy.
On a side note: i suspect you're trying to model page content here. Maybe you should refactor you database structure then as this table would have two responsibilities (url->content mapping and content).