How to change SQL WHERE clause through excel? - sql

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

Related

How to edit a query in Apache Superset?

I'd like to change the query so that the metrics / labels are different. So instead of the chart saying "sum_sum_girls", it would say something like "Total Girls" instead.
Current query is as follows:
SELECT state AS state,
SUM(sum_girls) AS sum__sum_girls
FROM birth_names
WHERE ds >= '1918-05-11 00:00:00.000000'
AND ds <= '2018-05-11 18:03:20.000000'
AND state NOT IN ('other')
GROUP BY state
ORDER BY sum__sum_girls DESC
LIMIT 50000
OFFSET 0;`enter code here`
I'd like to change it so it says
SELECT state AS state,
SUM(sum_girls) AS Total_Girls
FROM birth_names
WHERE ds >= '1918-05-11 00:00:00.000000'
AND ds <= '2018-05-11 18:03:20.000000'
AND state NOT IN ('other')
GROUP BY state
ORDER BY sum__sum_girls DESC
LIMIT 50000
OFFSET 0;
Any advice? Tried Googling to no avail. I'm used to being able to create easy custom SQL queries in Tableau.
You should be able to create custom queries by navigating to 'SQL Lab' > 'SQL Editor'.
You should then be able to create queries and re-use them in your graph.
See "Creating Datasources Using SQL Lab" on https://duperset.com/getting_started
Not sure if this is what you are looking for, but I'm gonna try.
For a chart you can define a Verbose Name for any metric you have. This is going to be the name displayed as a legend to the chart.
To do so, please go to the Datasuource(sometimes it is also called Table) you use for the chart and there to the List Metrics tab.
Go to Edit Datasource and in tab Metrics define metrics and its labels which will be shown in the chart.
Another approach is to define it directly in chart like in the picture below:

Compare dates using Dateserial in Access 2007 SQL

I have the following SQL
SELECT P1.Column1, P1.NextApprovalDate
FROM Procedures P1
WHERE DATESERIAL(YEAR(P1.NextApprovalDate), MONTH(P1.NextApprovalDate), 1 )
= DATESERIAL(YEAR(Date()), MONTH(DATE()) + 1, 1);
I get an error which is "Data type mismatch in criteria expression". I tried using the CDate and the Format functions in conjunction as well but continue to get the same error. The SQL runs fine when I am selecting the criteria there. How should the criteria be formatted?
Ok. I got this to work but it is kind of weird the way Access wanted it. The = sign never worked for the comparison. Why I don't know. The BETWEEN worked. If someone could find a way to make the '=' work, do let me know. Thanks to #Hansup for pointing me in the right direction.
SELECT P2.Column1, P2.NextApprovalDate
FROM (SELECT Procedures.Column1, Procedures.NextApprovalDate FROM
Procedures WHERE Procedures.NextApprovalDate IS NOT NULL) AS P2
WHERE DATESERIAL(YEAR(P2.NextApprovalDate),MONTH(P2.NextApprovalDate),1)
Between DATESERIAL(YEAR(Date()),MONTH(Date())+1,1) And
DATESERIAL(YEAR(Date()),MONTH(Date())+1,1);

How to remove from one list all the items in another?

I'm reading a set of rows from a remote database, and a similar set from a local database, and then using RemoveAll to get rid of remote rows that are already present locally...
remote_events = (From a In remote.Events
Where ...etc...).ToList
local_events = (From a In local.Events
Where ...etc...).ToList
remote_events.RemoveAll(Function (ByVal event_row As Remote_Event)
(From a In local_events Where a.Identifier = event_row.Identifier).Count > 0)
but this doesn't seem right to me. I don't think I should be counting things when all I really need to do is check whether a match exists. I've tried various usages of IsDBNull and IsNothing but get nonsense. I can't use .Except (as suggested here) because the list elements are not the same type.
Is there a better way of doing this?
One way is this:
remote_events.RemoveAll(Function(e) local_events.Exists(Function(f) f.Identifier = e.Identifier))
I'm trying to do this without visual studio, so I'm not sure if this will work, but I'd suppose you could do something along these lines if what you're trying to do is compare the Identifier:
Remote_Events = (From r_evt In Remote_Events
Where Not ((From l_evt In Local_Events Select l_evt.Identifier).Contains(r_evt.Identifier))
Select r_evt).ToList
I hope this helps and at least moves you in the right direction.

MOSS 2007: What is the source of "Directories"?

I'm trying to generate a new SharePoint list item directly using SQL server. What's stopping me is damn tp_DirName column. I have no ideas how to create this value.
Just for instance, I have selected all tasks from AllUserData, and there are possible values for the column: 'MySite/Lists/Task', 'Lists/Task' and even 'MySite/Lists/List2'.
MySite is the FullUrl value from Webs table. I can obtain it. But what about 'Lists/Task' and '/Lists/List2'? Where they are stored?
If try to avoid SQL context, I can formulate it the following way: what is the object, that has such attribute as '/Lists/List2'? Where can I set it up in GUI?
Just a FYI. It is VERY not supported to try and write directly to SharePoint's SQL Tables. You should really try and write something that utilizes the SharePoint Object Model. Writing to the SharePoint database directly mean Microsoft will not support the environment.
I've discovered, that [AllDocs] table, in contrast to its title, contains information about "directories", that can be used to generate tp_DirName. At least, I've found "List2" and "Task" entries in [AllDocs].[tp_Leaf] column.
So the solution looks like this -- concatenate the following 2 components to get tp_DirName:
[Webs].[FullUrl] for the web, containing list, containing item.
[AllDocs].[tp_Leaf] for the list, containing item.
Concatenate the following 2 components to get tp_Leaf for an item:
(Item count in the list) + 1
'_.000'
Regards,
Well, my previous answer was not very useful, though it had a key to the magic. Now I have a really useful one.
Whatever they said, M$ is very liberal to the MOSS DB hackers. At least they provide the following documents:
http://msdn.microsoft.com/en-us/library/dd304112(PROT.13).aspx
http://msdn.microsoft.com/en-us/library/dd358577(v=PROT.13).aspx
Read? Then, you know that all folders are listed in the [AllDocs] table with '1' in the 'Type' column.
Now, let's look at 'tp_RootFolder' column in AllLists. It looks like a folder id, doesn't it? So, just SELECT the single row from the [AllDocs], where Id = tp_RootFolder and Type = 1. Then, concatenate DirName + LeafName, and you will know, what the 'tp_DirName' value for a newly generated item in the list should be. That looks like a solid rock solution.
Now about tp_LeafName for the new items. Before, I wrote that the answer is (Item count in the list) + 1 + '_.000', that corresponds to the following query:
DECLARE #itemscount int;
SELECT #itemscount = COUNT(*) FROM [dbo].[AllUserData] WHERE [tp_ListId] = '...my list id...';
INSERT INTO [AllUserData] (tp_LeafName, ...) VALUES(CAST(#itemscount + 1 AS NVARCHAR(255)) + '_.000', ...)
Thus, I have to say I'm not sure that it works always. For items - yes, but for docs... I'll inquire into the question. Leave a comment if you want to read a report.
Hehe, there is a stored procedure named proc_AddListItem. I was almost right. MS people do the same, but instead of (count + 1) they use just... tp_ID :)
Anyway, now I know THE SINGLE RIGHT answer: I have to call proc_AddListItem.
UPDATE: Don't forget to present the data from the [AllUserData] table as a new item in [AllDocs] (just insert id and leafname, see how SP does it itself).

Translate SQL to OCL?

I have a piece of SQL that I want to translate to OCL. I'm not good at SQL so I want to increase maintainability by this. We are using Interbase 2009, Delphi 2007 with Bold and modeldriven development. Now my hope is that someone here both speaks good SQL and OCL :-)
The original SQL:
Select Bold_Id, MessageId, ScaniaId, MessageType, MessageTime, Cancellation, ChassieNumber, UserFriendlyFormat, ReceivingOwner, Invalidated, InvalidationReason,
(Select Parcel.MCurrentStates From Parcel
Where ScaniaEdiSolMessage.ReceivingOwner = Parcel.Bold_Id) as ParcelState From ScaniaEdiSolMessage
Where MessageType = 'IFTMBP' and
not Exists (Select * From ScaniaEdiSolMessage EdiSolMsg
Where EdiSolMsg.ChassieNumber = ScaniaEdiSolMessage.ChassieNumber and EdiSolMsg.ShipFromFinland = ScaniaEdiSolMessage.ShipFromFinland and EdiSolMsg.MessageType = 'IFTMBF') and
invalidated = 0 Order By MessageTime desc
After a small simplification:
Select Bold_Id, (Select Parcel.MCurrentStates From Parcel
where ScaniaEdiSolMessage.ReceivingOwner = Parcel.Bold_Id) From ScaniaEdiSolMessage
Where MessageType = 'IFTMBP' and not Exists (Select * From ScaniaEdiSolMessage
EdiSolMsg Where EdiSolMsg.ChassieNumber = ScaniaEdiSolMessage.ChassieNumber and
EdiSolMsg.ShipFromFinland = ScaniaEdiSolMessage.ShipFromFinland and
EdiSolMsg.MessageType = 'IFTMBF') and invalidated = 0
NOTE: There are 2 cases for MessageType, 'IFTMBP' and 'IFTMBF'.
So the table to be listed is ScaniaEdiSolMessage.
It has attributes like:
MessageType: String
ChassiNumber: String
ShipFromFinland: Boolean
Invalidated: Boolean
It has also a link to table Parcel named ReceivingOwner with BoldId as key.
So it seems like it list all rows of ScaniaEdiSolMessage and then have a subquery that also list all rows of ScaniaEdiSolMessage and name it EdiSolMsg. Then it exclude almost all rows. In fact the query above give one hit from 28000 records.
In OCL it is easy to list all instances:
ScaniaEdiSolMessage.allinstances
Also easy to filter rows by select for example:
ScaniaEdiSolMessage.allinstances->select(shipFromFinland and not invalidated)
But I do not understand how I should make a OCL to match the SQL above.
Listen to Gabriel and Stephanie, learn more SQL.
You state that you want to make the code more maintainable, yet the number of developers who understand SQL is greater by far than the number of developers who understand OCL.
If you leave the project tomorrow after converting this to OCL, the chances that you'd be able to find someone who could maintain the OCL are very slim. However, the chances that you could find someone to maintain the SQL are very high.
Don't try to fit a square peg in a round hole just because you're good with round hammers :)
There is a project, Dresden OCL, that might help you.
Dresden OCL provides a set of tools to parse and evaluate OCL constraints on various models like UML, EMF and Java. Furthermore Dresden OCL provides tools for Java/AspectJ and SQL code generation. The tools of Dresden OCL can be either used as a library for other project or as a plug-in project that extends Eclipse with OCL support.
I haven't used it, but there is a demo showing how the tool generates SQL from a model and OCL constraints. I realize you're asking for the opposite, but maybe using this you can figure it out. There is also a paper that describes OCL->SQL transformations by the same people.
With MDriven (successor of Bold for Delphi) I would do it like this:
When working with OCL to SQL everything becomes easier if you think about the different set's of information you need to check - and then use ocl operators as ->intersection to find the set you are after.
So in your case you might have a set like this:
ScaniaEdiSolMessage.allinstances->select(shipFromFinland and not invalidated)
but you also have a set like this:
ScaniaEdiSolMessage.allinstances->select(m|m.ReceivingOwner.MessageType = 'IFTMBP')
And you further more have this criteria:
Parcel.allinstances->select(p|p.Messages->exists(m|m.MessageType = 'IFTMBF')).Messages
If all these Sets have the same result type (collection of ScaniaEdiSolMessage) you can simply intersect them to get your desired result
ScaniaEdiSolMessage.allinstances->select(shipFromFinland and not invalidated)
->intersection(ScaniaEdiSolMessage.allinstances->select(m|m.ReceivingOwner.MessageType = 'IFTMBP'))
->intersection(Parcel.allinstances->select(p|p.Messages->exists(m|m.MessageType = 'IFTMBF')).Messages
)
And looking at that we can reduce it a bit to:
ScaniaEdiSolMessage.allinstances
->select(m|m.shipFromFinland and (not m.invalidated) and
(m.ReceivingOwner.MessageType = 'IFTMBP'))
->intersection(Parcel.allinstances->select(p|
p.Messages->exists(m|m.MessageType = 'IFTMBF')).Messages
)