How do I stop SSMS from editing my view query - ssms

Is there a way to force SSMS to use the exact query I paste into a view without it making changes? It is extremely annoying to me that I can write a working query and SSMS will make small or large changes to it that make it harder to read or not work at all. I have been trying to google this, but I have no idea how to put this into concise terms.
Example:
WHERE NOT(ClutchAssy.LineOpSta = '7701/040/004' AND LEN(TRIM(ClutchAssy.CompSN)) > 10)
AND NOT(ClutchAssy.LineOpSta = '7701/030/003' AND LEN(TRIM(ClutchAssy.CompID)) >= 5)
gets turned into
WHERE (NOT (LineOpSta = '7701/040/004')) AND (NOT (LineOpSta = '7701/030/003'))
OR (NOT (LineOpSta = '7701/040/004')) AND (NOT (LEN(TRIM(CompID)) >= 5))
OR (NOT (LineOpSta = '7701/030/003')) AND (NOT (LEN(TRIM(CompSN)) > 10))
OR (NOT (LEN(TRIM(CompID)) >= 5)) AND (NOT (LEN(TRIM(CompSN)) > 10))
In this case, both WHERE statements seem to be functionally identical, but if I want to work on this view in the future it is extremely annoying to have to work from these changes rather than what I wrote myself. Does anyone know how to stop this from happening, or at least know why this happens? Thank you for helping me learn.

Related

SQL Selection Query getting corrupted

Ive come across a very unusual problem (for me at least) and I have no idea how to solve it.
Essentially I made a really simple selection query to search our clients in a table (dbo_t_Person) and return their records. I needed them to be searchable even if we only have an email address, or phone number for some clients on hand. Therefore I wrote the criteria to either ignore a field if no data was entered, or to search similar (via 'Like') if only partial details were entered into any given field. See the SQL below, apologies for how repetitive it is.
This is all well and good, it works perfectly and is fast enough for our uses.
However.
I can run the query as many times as I wish with new data entered and it works fine, but if I close the query and reopen it, the SQL goes haywire and it runs out of memory and crashes access, this is crashing just opening the SQL as well as running it. By haywire I mean that if i manage to luck out and reopen the SQL, lines of SQL are suddenly copied endlessly on the page.
This happens every time I rewrite the SQL from scratch, how the hell do I stop this happening?
Here is the working clean code:
SELECT dbo_t_Person.PersonID
,dbo_t_Person.FullName
,dbo_t_Person.Address1
,dbo_t_Person.Address2
,dbo_t_Person.City
,dbo_t_Person.Zip
,dbo_t_Person.STATE
,dbo_t_Person.Country
,dbo_t_Person.Mobile
,dbo_t_Person.Phone
,dbo_t_Person.Email
FROM dbo_t_Person
WHERE (
(
(dbo_t_Person.PersonID) = [Forms]![from MICHAEL TEST WORKING]![OwnerIDEntry]
OR [Forms]![from MICHAEL TEST WORKING]![OwnerIDEntry] IS NULL
)
AND (
(dbo_t_Person.FullName) LIKE "*" & [Forms]![from MICHAEL TEST WORKING]![NameEntry] & "*"
OR [Forms]![from MICHAEL TEST WORKING]![NameEntry] IS NULL
)
)
And so on for the remaining entry fields
However if I can get the SQL back open again it it appears thousands of lines of
Or [Forms]![from MICHAEL TEST WORKING]![NameEntry] Is Null
for all entry fields is endlessly repeated.
Something is making the code copy end on end, how do I stop it?
Consider an adjusted WHERE clause with NZ() to handle if controls are empty or not.
WHERE dbo_t_Person.PersonID = NZ([Forms]![from MICHAEL TEST WORKING]![OwnerIDEntry],
dbo_t_Person.PersonID)
AND dbo_t_Person.FullName = LIKE "*" & NZ([Forms]![from MICHAEL TEST WORKING]![NameEntry],
dbo_t_Person.FullName) & "*"
Try changing your criteria to be more efficient and clean, like this:
IIF(ISNULL([Forms]![from MICHAEL TEST WORKING]![OwnerIDEntry]),TRUE,PersonID=[Forms]![from MICHAEL TEST WORKING]![OwnerIDEntry])
Since you are only dealing with a single table you can also do away with dbo_t_Person. from everywhere, like this:
SELECT PersonID,FullName,Address1,Address2,City,Zip,STATE,Country,Mobile,Phone,Email
FROM dbo_t_Person
Maybe the simplified version of the SQL will stop Access from corrupting it.

How to change SQL WHERE clause through excel?

I have build a SQL query to provide me historical price data of a product, which I intent to use in excel (pivot, graphs, all of that fancy excel stuff).
The problem now is that, due to the nature of many products and many price changes, I can not get all the products loaded that I intent to.
I somehow need to tell excel that has to change a couple numbers in the connected SQL query, i.e. through a text box and then load the query again. Otherwise I will always open up the query editor in excel and change it manually, which takes quite a bit.
I reckon I will have to use some sort of macro or VBA, but I have never used it. If anyone could refer an article that would be great, as i could not find anything helpful.
Some code:
WHERE
PD.Product_Id = '11761476' < I will have to change that number
AND
PSPH.[Valid_To] > '2018-01-01'
ORDER BY
PSPH.[Valid_To]
To manipulate the SQL string, you could do something like this..
pid = "11761476"
validto = "2018-01-01"
SQLtemplate = "WHERE PD.Product_Id = '[prodID]' AND PSPH.[Valid_To] > '[validto]' ORDER BY PSPH.[Valid_To]"
Sql = Replace(SQLtemplate, "[prodID]", pid)
Sql = Replace(Sql, "[validto]", validto)
but before you can use that, you'll need to follow #Foxfire's advice and record a macro while you're changing it manually to see exactly what needs to change, and how.
You can put this instead in the connection:
WHERE
PD.Product_Id = '11761476' < ?
AND
PSPH.[Valid_To] > '2018-01-01'
ORDER BY
PSPH.[Valid_To]
And then save the connection.
The first time it will run, a prompt will ask you where to find the parameter, and you can choose the cell.
Let me know if it works!
Cheers,
Arnaud

System Date as a Clause

I'm using Oracle Business Intelligence, and creating a custom report. I've been able to create and have everything work except there's an issue in using parameters on scheduled reports.
This is forcing me to hard code the auto-updating dates in the Data model. Is anyone able to assist with the best way to replace my parameters below?
Essentially, I'm looking for START_DATE_PARAMETER to be replaced with the System Date MINUS 15, and END_DATE_PARAMETER to be replaces with System Date PLUS 1.
AND table1.EFFECTIVE_START_DATE >= :START_DATE_PARAMETER
AND table1.EFFECTIVE_START_DATE <= :END_DATE_PARAMETER
AND table2.EFFECTIVE_END_DATE >= :START_DATE_PARAMETER
AND table2.EFFECTIVE_END_DATE <= :END_DATE_PARAMETER
I appreciate everyone's feedback. I am fairly new to SQL, and am trying to develop my skills so all of the input is much appreciated.
Because my parameters are meant to include more than I'll actually need, I can potentially use either the 'CURRENT_TIMESTAMP' or 'SYSDATE' solution. The one piece of the puzzle that I was missing was the inclusion of 'TRUNC('
AND table1.EFFECTIVE_START_DATE >= (TRUNC(CURRENT_TIMESTAMP) - 15)
AND table1.EFFECTIVE_START_DATE <= (TRUNC(CURRENT_TIMESTAMP) + 1)
AND table2.EFFECTIVE_END_DATE >= (TRUNC(CURRENT_TIMESTAMP) - 15)
AND table2.EFFECTIVE_END_DATE <= (TRUNC(CURRENT_TIMESTAMP) + 1)

Best design patterns for refactoring code without breaking other parts

I have some PHP code from an application that was written using Laravel. One of the modules was written quite poorly. The controller of this module has a whole bunch of reporting functions which uses the functions defined inside the model object to fetch data. And the functions inside the model object are super messy.
Following is a list of some of the functions from the controller (ReportController.php) and the model (Report.php)(I'm only giving names of functions and no implementations as my question is design related)
Functions from ReportController.php
questionAnswersReportPdf()
fetchStudentAnswerReportDetail()
studentAnswersReport()
wholeClassScoreReportGradebookCSV()
wholeClassScoreReportCSV()
wholeClassScoreReportGradebook()
formativeWholeClassScoreReportGradebookPdf()
wholeClassScoreReport()
fetchWholeClassScoreReport()
fetchCurriculumAnalysisReportData()
curriculumAnalysisReportCSV()
curriculumAnalysisReportPdf()
studentAnswersReportCSV()
fetchStudentScoreReportStudents()
Functions from Report.php
getWholeClassScoreReportData
getReportsByFilters
reportMeta
fetchCurriculumAnalysisReportData
fetchCurriculumAnalysisReportGraphData
fetchCurriculumAnalysisReportUsersData
fetchTestHistoryClassAveragesData
fetchAllTestHistoryClassAveragesData
fetchAllTestHistoryClassAveragesDataCsv
fetchHistoryClassAveragesDataCsv
fetchHistoryClassAveragesGraphData
The business logic has been written in quite a messy way also. Some parts of it are in the controller while other parts are in the model object.
I have 2 specific questions :
a) I have an ongoing goal of reducing code complexity and optimizing code structure. How can I leverage common OOP design patterns to ensure altering the code in any given report does not negatively affect the other reports? I specifically want to clean up the code for some critical reports first but want to ensure that by doing this none of the other reports will break.
b) The reporting module is relatively static in definition and unlikely to change over time. The majority of reports generated by the application involve nested sub-queries as well as standard grouping & filtering options. Most of these SQL queries have been hosed within the functions of the model object and contain some really complex joins. Without spending time evaluating the database structure or table indices, which solution architecture techniques would you recommend for scaling the report functionality to ensure optimized performance? Below is a snippet of one of the SQL queries
$sql = 'SELECT "Parent"."Id",
"Parent"."ParentId",
"Parent"."Name" as systemStandardName,
string_agg(DISTINCT((("SubsectionQuestions"."QuestionSerial"))::text) , \', \') AS "quesions",
count(DISTINCT("SubsectionQuestions"."QuestionId")) AS "totalQuestions",
case when sum("SQUA"."attemptedUsers")::float > 0 then
(COALESCE(round((
(
sum(("SQUA"."totalCorrectAnswers"))::float
/
sum("SQUA"."attemptedUsers")::float
)
*100
)::numeric),0))
else 0 end as classacuracy,
case when sum("SQUA"."attemptedUsers")::float > 0 then
(COALESCE((round(((1 -
(
(
sum(("SQUA"."totalCorrectAnswers"))::float
/
sum("SQUA"."attemptedUsers")::float
)
)
)::float * count(DISTINCT("SubsectionQuestions"."QuestionId")))::numeric,1)),0))
else 0 end as pgain
FROM "'.$gainCategoryTable.'" as "Parent"
'.$resourceTableJoin.'
INNER JOIN "SubsectionQuestions"
ON "SubsectionQuestions"."QuestionId" = "resourceTable"."ResourceId"
INNER JOIN "Subsections"
ON "Subsections"."Id" = "SubsectionQuestions"."SubsectionId"
LEFT Join (
Select "SubsectionQuestionId",
count(distinct case when "IsCorrect" = \'Yes\' then CONCAT ("UserId", \' \', "SubsectionQuestionId") else null end) AS "totalCorrectAnswers"
, count(distinct CONCAT ("UserId", \' \', "SubsectionQuestionId")) AS "attemptedUsers"
From "SubsectionQuestionUserAnswers"';
if(!empty($selectedUserIdsArr)){
$sql .= ' where "UserId" IN (' .implode (",", $selectedUserIdsArr).')' ;
}else {
$sql .= ' where "UserId" IN (' .implode (",", $assignmentUsers).')' ;
}
$sql .= ' AND "AssessmentAssignmentId" = '.$assignmentId.' AND "SubsectionQuestionId" IN ('.implode(",", $subsectionQuestions).') Group by "SubsectionQuestionId"
) as "SQUA" on "SQUA"."SubsectionQuestionId" = "SubsectionQuestions"."Id"
INNER JOIN "AssessmentAssignment"
ON "AssessmentAssignment"."assessmentId" = "Subsections"."AssessmentId"
INNER JOIN "AssessmentAssignmentUsers"
ON "AssessmentAssignmentUsers"."AssignmentId" = "AssessmentAssignment"."Id"
AND "AssessmentAssignmentUsers"."Type" = \'User\'
'.$conditaionlJoin.'
WHERE "Parent"."Id" IN ('.implode(',', $ssLeaf).')
'.$conditionalWhere.'
GROUP BY "Parent"."Id",
"Parent"."ParentId",
"Parent"."Name"
'.$sorter;
$results = DB::select(DB::raw($sql));
My take on a). In my experience when I want to reduce code complexity/sheer messiness I slowly refactor out code that violates the single responsibility principle while I'm working in that area already for either a bug fix or a feature update. I try not to spend hours upon hours of updating code that is "working" that I'm not actively updating for a business process reason. Follow the "Leave it better than you found it" approach as you work in this code base, and it will get better over time. Doing this will allow you to improve the code base while also getting features and bug fixes out the door, while also keeping business owners/project managers happy because you're keeping things moving.
about a) : The first thing I do, to ensure none of my refactoring is breaking anything, is covering the code with, at least, unitary tests (doing TDD ensures the most optimal coverage). It's easier when, like #DavidY says, you respect principles like SRP (does my class try to answer too many problems ?). With test, you'll feel safer when you'll need to refactor, and the tests will tell you exactly where it broke.
about b) : Do not optimize until you need it. And optimize only when you know what cost you the most. It's the best way to know what pattern you need, otherwise you may try to force the wrong solution into the wrong problem.

phalcon querybuilder total_items always returns 1

I make a query via createBuilder() and when executing it (getQuery()->execute()->toArray())
I got 10946 elements. I want to paginate it, so I pass it to:
$paginator = new \Phalcon\Paginator\Adapter\QueryBuilder(array(
"builder" => $builder,
"limit" => $limit,
"page" => $current_page
));
$limit is 25 and $current_page is 1, but when doing:
$paginator->getPaginate();
$page->total_items;
returns 1.
Is that a bug or am I missing something?
UPD: it seems like when counting items it uses created sql with limit. There is no difference what limit is, limit divided by items per page always equals 1. I might be mistaken.
UPD2: Colleague helped me to figure this out, the bug was in the query phalcon produces: count() of the group by counts grouped elements. So a workaround looks like:
$dataCount = $builder->getQuery()->execute()->count();
$page->next = $page->current + 1;
$page->before = $page->current - 1 > 0 ? $page->current - 1 : 1;
$page->total_items = $dataCount;
$page->total_pages = ceil($dataCount / 100);
$page->last = $page->total_pages;
I know this isn't much of an answer but this is most likely to be a bug. Great guys at Phalcon took on a massive job that is too big to do it properly in their little free time and things like PHQL, Volt and other big but non-core components do not receive as much attention as we'd like. Also given that most time in the past 6 months was spent on v2 there are nearly 500 bugs about stuff like that and it's counting. I came across considerable issues in ORM, Volt, Validation and Session, which in the end made me stick to other not as cool but more proven solutions. When v2 comes out I'm sure all attention will on the bug list and testing, until then we are mostly on our own. Given that it's all C right now, only a few enthusiast get involved, with v2 this will also change.
If this is the only problem you are hitting, the best approach is to update your query to get the information you need yourself without getPaginate().