Return single value based on conditional CASE - mysql

I have no background with MySQL and have not been able to find the appropriate stepping stones to accomplish writing this particular query.
Objective:
I have created a report that shows the approval status of artwork per page. Artists have to access the proof however to determine if there is any markup/notes on each page. I want to add single column to the report that will have one of three string values per page for each proof. The string will either be "Yes", No", or "Missed" based on certain conditions.
Each proof can have multiple pages. Each page can have multiple marks (think of drawing a circle around something). Each mark can have multiple notes. This is where, for me, things get hazy. I am aware of the need to avoid RBAR queries, but I am unsure how to query against multiple comments and then marks by page.
Conditions:
This is the RBAR query I have for handling the notes/comments. This is fine for dealing with each comment, but obviously on a report there is no reason to see each comment row.
SELECT *,
CASE WHEN note IS NULL OR ' ' AND deleted = FALSE
THEN 'Missed' ELSE 'Yes'
END AS 'Comment'
FROM rvm_comment
Knowing that a mark can have multiple comments, I need to determine if any rows in rvm_comment.note are NOT NULL or contain just a space, ' '. If so, the mark is represented as "Yes". Otherwise the mark would be "Missed".
This should then be condensed/nested in a manner that each mark is compared.
If any mark on a page is "Yes" then output in that row would be "Yes". Otherwise, "Missed".
If this doesn't make sense, hopefully the following information will shed some light.
Tables and Relationships:
DSE_OBJECT Table:
This table is associated with a request that a proof can be attached to. The ID is the PK.
RVM_REVIEW_OBJECT Table:
This table is essentially the proof instance itself. A proof can have any number of pages (min 1). ID is the PK, review_object is the FK.
RVM_MARK Table:
This table contains information on marks that are added to a proof, including the page they exist on. ID is the PK, review_object is the FK. (NOT LISTED) Deleted is used to prevent returning results where a mark is deleted by the user. rvm_mark.deleted = FALSE
RVM_COMMENT Table:
This table is where the notes (strings) are stored. Deleted is used to prevent returning results where a note is deleted by the user (rvm_comment.deleted = FALSE). There is a flaw in the system where a comment can be created but if the user doesn't hit "enter" on their keyboard after typing the text is not saved in to the DB. This is why we need to test for NULL in rvm_comment.note.
Raw Data for Testing and Summary: Dropbox with CSVs for the tables
As a courtesy I have included some raw data in CSV form for anyone will to try it out. (click Dropbox link above).
So, to summarize again. I am trying to write a query that will condense those tables to a single string (AS Comment),for each rvm_mark.page_no. The string is based on a) whether or not rvm_comment.note is NULL or ' ', and b) whether any rvm_mark.id that has matching rvm_mark.page_no, has rvm_comment.note that isn't NULL.
EDIT UPDATE 12/14/16:
Thanks to Barmar I was able to take a step towards the final result. I am currently stuck on trying to return the string 'No' for any situations where there are no comments. This should only be when rvm_review_object.id does not have a matching value in rvm_mark.review_object.
SELECT rvm_review_object.dse_object_id, rvm_review_object.id,
T_Mark.creator, T_Mark.review_object,
CASE WHEN T_Mark.review_object IS NULL THEN 'No'
ELSE T_Mark.Comment
END AS Comment
FROM rvm_review_object
LEFT JOIN(
SELECT rvm_mark.review_object, rvm_mark.creator, rvm_mark.id,
CASE WHEN MAX(T_Comment.Comment = 'Yes') = 1 THEN 'Yes'
ELSE 'Missed'
END AS Comment
FROM rvm_mark
LEFT JOIN(
SELECT rvm_comment.mark,
CASE WHEN MAX((rvm_comment.note IS NULL OR rvm_comment.note = '')
AND rvm_comment.deleted = FALSE) = 1
THEN 'Missed'
ELSE 'Yes'
END AS Comment
FROM rvm_comment
GROUP BY rvm_comment.mark) AS T_Comment
ON T_Comment.mark = rvm_mark.id
WHERE rvm_mark.deleted = FALSE
GROUP BY rvm_mark.review_object) AS T_Mark
ON T_Mark.review_object = rvm_review_object.id
WHERE rvm_review_object.creator != T_Mark.creator

You need to group the query by mark. You can then use MAX() to determine if any of the rows in the group match the condition.
SELECT mark,
CASE WHEN MAX((note IS NULL OR note = '') AND deleted = FALSE) = 1
THEN 'Missed'
ELSE 'Yes'
END AS Comment
FROM rvm_comment
GROUP BY mark

Related

NetSuite Saved Search where {location} = {user.location}?

This seems like it should be simple, but for some reason I can't get this to work... I am trying to build a transaction saved search that shows the user (person viewing the search) all transfer orders that have their location in either the {location} field or {transferlocation} field. Here is the formula (Numeric) I am adding to the criteria and setting is equal to 1:
CASE WHEN {location} = {user.location} THEN 1 ELSE 0 END
Seems pretty simple, but this formula errors out. I have also tried this and it doesn't error, but I get 0 results:
CASE WHEN {location} LIKE {user.location} THEN 1 ELSE 0 END
Once I get this to succeed I should be able to either add to this formula or add a new formula criteria for the {transferlocation}. Either way, any suggestions would be great. Below I will add all criteria/results/filters just for transparency:
Criteria:
Main Line is True
Type is Transfer Order
Status is any of Transfer Order:Partially Fulfilled, Transfer Order:Pending Approval, Transfer Order:Pending Fulfillment, Transfer Order:Pending Receipt, Transfer Order:Pending Receipt/Partially Fulfilled
(not working) Formula (Numeric) is 1 CASE WHEN {user.location} = {location} OR {user.location} = {transferlocation} THEN 1 ELSE 0 END
Results:
Date Created
Document Number
Location
To Location
Filters:
Date Created
In a lot of case, when you use Numeric Formula, it seems like NS prefer using internalIds, so use this in your formula and it should work (tested):
CASE WHEN {location.id} = {user.location.id} THEN 1 ELSE 0 END
Most likely due to NetSuite perceiving the possibility of data type differences. Try wrapping your location fields in NVL and/or TO_CHAR or using ...location.id}

Access writng to wrong row number

4150
NRrows = RSNonResourceCosts.RecordCount ' Number of Rows in Non Resource Table
NRCols = RSNonResourceCosts.Fields.Count ' Number of Fields in NonResource Table
Dim CL(1 To 10) As Integer ' This is to count "filled rows" when spreadsheet is filled
Dim Header(1 To 10) As String
'-----------
'Find the Headers (Taken from Actual Table and not predefined as original)
For Each Recordsetfieldx In RSNonResourceCosts.Fields
If C > 0 Then
Header(C) = Recordsetfieldx.Name
End If
C = C + 1
Next Recordsetfieldx
4170
R = 0
'Write to worksheet
RSNonResourceCosts.MoveFirst
Do Until RSNonResourceCosts.EOF
For C = 1 To NRCols - 1
FieldName = RSNonResourceCosts.Fields(C).Value
If RSNonResourceCosts.Fields(Header(C)).Value <> "" Then
CL(C) = CL(C) + 1
WKS.Cells(200 + R, C) = RSNonResourceCosts.Fields(Header(C)).Value
End If
Next C
RSNonResourceCosts.MoveNext
R = R + 1
Loop
I attach code. Have solved part of original by defining Recordset. User can add column to Table. First part of code determines the headers. Second part determines values and writes to worksheet. The new Rows are appearing first on the worksheet and in wrong column. I tried attaching worksheet but it looked awful. Any help would be appreciated.
Two things:
1) The order your records is the order they are in the recordset. If you want them in a particular order, try sorting them (perhaps with an ORDER BY in the underlying SQL statement)
2) For the column issue: In the first bit of code, I don't see where C is initialized, but keep in mind the Headers and Fields both start with an index of 0, so if you set Header(1) = the first field's header (index 0), but then copy the data in the fields without shifting the index value, it will shift everything over by one column.
As an added note, you might want to consider what happens when you have more than 10 columns. Using fixed-length arrays means your code will break. You might want to read about using a dynamic array and ReDim.
I don't yet feel like I have completely grasped the entirety of the problem yet, but let me take a stab at it. From what I do understand, data is being written from your record set into excel (good), but it is going into the 'wrong row' (question title) and the 'wrong column' (question text).
From what I see, I don't know the purpose of FieldName = RSNonResourceCosts.Fields(C).Value, but I want to make sure that you understand that RSNonResourceCosts.Fields(C).Value is not necessarily equivalent to RSNonResourceCosts.Fields(Header(C)).Value. More than that, you are likely missing at least one column altogether in your output, or at least skipping over it accidentally. rs.Fields(0).name is the first 'column' in a recordset, but it is completely ignored in your code. Perhaps this is intentional, maybe it is a key field or something useless to you, but it is important that you are making that distinction intentionally. But, since I don't see where your code populates the headers in your worksheet, I wonder if 'wrong column' means every record has been shifted a column and your last column is sitting empty. That, coupled with the dubious omission of C being initialized as 0 (not 1, or anything else) in your above code, makes me concerned that Header(3) could possibly by field(1), or field(4), or I don't know. That would certainly also confuse the columns in your output, or at least make dependence on FieldName frustrating.
Another thing, really a shot in the dark: NRrows. I have had issues before, depending on how I create my recordset, of not getting the correct record count the first time. And, if I base the population of a worksheet, array, etc., on the number of rows and the records relative position in that number, my records get all sorts of wacky. Maybe you did this already, but since it isn't shown, I recommend a RSNonResourceCosts.movelast: RSNonResourceCosts.movefirst line before you define NRrows, just to be sure.
And last, if I am way off base here... then you really are going to have to show us the spreadsheet, even if it isn't your most beautiful work. We all know that if it were, you wouldn't be asking about it here... so set your pride aside, and be more specific as well as show us what the output looks like and how it should look.

In MS Access 2010 I'm trying to ignore a duplicate entry in a control

I want to ignore duplicate entries in specific text fields on a form. So, for example, I have 3 fields for seal entry. If the person scans a seal twice, it will ignore the duplicate and keep the focus on the field until a different number is entered. I cobbled together some code that works for the first and second entry, but not the third. When I debug it seems to be finding a duplicate number even though I'm entering in a different one.
Private Sub Seal2_AfterUpdate()
If Seal2.Value = Seal1.Value Or Seal3.Value Then
Seal2.Value = Null
Seal1.SetFocus
Seal2.SetFocus
End If
End Sub
Private Sub Seal3_AfterUpdate()
If Seal3.Value = Seal1.Value Or Seal2.Value Then
Seal3.Value = Null
Seal1.SetFocus
Seal3.SetFocus
End If
End Sub
You are treating the Or wrong. It's evaluating after the Seal2.Value = Seal1.Value.
So what you have done in that if statement is equivalent to
If (Seal3.Value = Seal1.Value) Or Seal2.Value Then
And since Seal2 has a value, it is evaluating to True
You want something more like:
If (Seal3.Value = Seal1.Value) Or (Seal3.Value = Seal2.Value) Then
Also, you seem to be setting focus to one field and then another. You probably want to only go to one unless you are trying to fire off triggers/events when you get/lose focus in each one; however, if you are doing that you might be playing with fire
In the end your if blocks probably want to look like this:
If (Seal2.Value = Seal1.Value) Or (Seal2.Value = Seal3.Value) Then
Seal2.Value = Null
Seal2.SetFocus
End If
and
If (Seal3.Value = Seal1.Value) Or (Seal3.Value = Seal2.Value) Then
Seal3.Value = Null
Seal3.SetFocus
End If
Finally, if you find that you have to expand beyond 3 fields, you may want take a slightly different approach that would be more scalable. E.g., Building up a list in memory, sorting and filtering it. But for 3 or 4 items you can get away with what you have already.

Append string to another table in MySQL

I’ve got a problem selecting some things in my database.
I’ve got 1 database with a lot of tables, however I only use 2 with this specific task.
I have a Clothing table, and I need to import this in my new database. I have succesfully transferred a lot of data, but now I need to take 1 final small step into completing this. In my Clothing table I have a column called Youtube link, here I have a link with an Youtube link, this specific link, in this specific column, I want to append that to another table I have in the database, let’s call it new_clothing_table. I there have a description column called prod_desc and I want to append the Youtube link to that column.
But there is also another “problem”, it’s not that every product has a Youtube link, so things have to be filtered in order to not fuck things royally up. A advantage I have, I have in both tables a product_name, and these are all the same. So I want to transfer that specific Youtube link if it’s there (sometimes there is a 0 filled in or nothing, but I dont think it’s NULL because if I make a SELECT query where Youtube_link is null I get zero rows..)
So can someone help me out>?
mysql has an update-join construct you can use:
UPDATE new_clothing_table nct
JOIN clothing c ON c.product_name = nct.product_name AND
c.youtube_link != '0'
SET nct.description = CONCAT(nct.description, c.youtube_link)
EDIT:
To make sure this does what you want, you could first select the updated content in order to examine it:
SELECT nct.description AS old_description,
CONCAT(nct.description, c.youtube_link) AS new_description
FROM new_clothing_table nct
JOIN clothing c ON c.product_name = nct.product_name AND
c.youtube_link != '0'

MySQL modify values of one column based on contents of another

Basically I want to query a database and modify the values of one column based on the contents of another.
Here's my idea of how it would work:
IF Column 'Town' IS NOT NULL then Column 'Sign-up type' = 1 else = 0
The logic is, i've added a new column into the DB that will store whether a quick or full sign up has been made.
Quick = 0, Full = 1. Default is 0 = Quick.
I've managed to implement the change on the two registration forms that feed the DB, but I need to append the historical data to backwards fill the data.
Because the quick sign up only collects name, and email, those entries do not contain data in the 'Town' field which is a required field in a full sign up.
So i'm using that as a reference point to select all the entries that DO have (NOT NULL?) data in order to enter '1' (representing 'Full') into 'Signup Type' column.
I hope I'm making sense! I only have a basic understanding of MySQL but I'm willing to learn, it's sometimes hard trying to explain what I want to do when I'm unclear of the correct jargon!!
UPDATE yourTable SET signupType = IF(Town IS NULL, 1, 0);
Note this will update all data, you may want to limit this to historical data (by the sounds of things this should be fine however).