Sharing views between BigQuery projects - view

I am using Google BigQuery to analyze data for several clients with same algorithms . All projects have same Location. Those algorithms are views.
Is it possible to have those views at only one project, and run it over different project data?
Thanks

Yes. While view is in one project - data/tables referenced in it can reside in another project.
Btw, using this "model" you can "separate" users from having access to actual data by giving them access to View ONLY, while sharing respective dataset with this View using "Authorized View" option
I don't want to create views for every project, but run the view over
different projects without any change
Generically speaking, as of today, this is not possible!
Till when Views will support passing parameters/arguments or something like this
Still, I see one option for below particular case!
If you have exactly same logic and data schema and only what is different for different clients is project - you should use something like below (just an idea to explore)
SELECT * FROM
(SELECT * FROM [projectA:dataset.table] WHERE CURRENT_USER() IN ('name1#clientA.com', 'name2#clientA.com')),
(SELECT * FROM [projectB:dataset.table] WHERE CURRENT_USER() IN ('name1#clientB.com', 'name2#clientB.com')),
(SELECT * FROM [projectC:dataset.table] WHERE CURRENT_USER() IN ('name1#clientC.com', 'name2#clientC.com'))
So, depends on which user is running View - respective data will be served.
Of course in this case - using Authorized View as option for Sharing Data is a MUST, so clientA has no any access to ClientB or ClientC data
Above example can be modified to below
SELECT * FROM
(SELECT *, 'ClientA' AS client FROM [projectA:dataset.table]),
(SELECT *, 'ClientB' AS client FROM [projectB:dataset.table]),
(SELECT *, 'ClientC' AS client FROM [projectC:dataset.table])
so the view can be used as below
SELECT * FRIN YourView WHERE client = 'ClientB'
IMPORTANT
Please have in mind that above abstract/theoretical options will lead you to be charged for querying ALL involved projects each and every time you run it. even though you will get result only related to specific project/client.
I dont think you want this to happen

Related

Redshift View keeps reverting to previous definition

I created a view in Redshift that unions two queries, and it works great. We've thought of a third query that would be worthwhile to add in. eg
CREATE VIEW stem_alumni as
SELECT name, email
FROM students
WHERE graduated < 2019 AND major = 'Engineering'
UNION
SELECT name, email
FROM alumni
WHERE current_employer = 'Google'
The problem is when I try to add a third query in
UNION
SELECT name, email
FROM professors
WHERE department = 'Engineering'
it'll persist for maybe an hour, but then revert to just the original query.
I've run CREATE OR REPLACE VIEW... and dropping/recreate and get the same result.
How do I get an updated view definition to persist?
Adding more context
I created the view using DBeaver, a local SQL client using my specific Redshift credentials. The view is called by Periscope, our cloud-based BI tool using shared credentials. Querying the view in Periscope or separate DBeaver windows will eventually revert the view to its original definition.
Redshift shouldn't have a 'memory' of the view's prior DDL that it could revert to. I'm inclined to agree with the comments that something else is overwriting the updates to the view's DDL after you have committed them.
You should be able to see if something is overwriting the view, by querying the stl_query table:
SELECT q.starttime
, u.usename
, q.querytxt
FROM pg_user u
JOIN stl_query q ON u.usesysid = q.userid
WHERE POSITION('<view_name>' IN q.querytxt) > 0
ORDER BY q.starttime DESC
;
This table only contains recent query information (2-5 days according to the Redshift Documentation), so if you haven't experienced this behavior from the view within that timescale, you may need to force it to occur again in order to troubleshoot who/what is altering the DDL.
Additionally, if the view is being overwritten by a user other than yourself, you will need to query stl_query using a super user account (by default, non-super users will only be able to view information for queries that they themselves have executed).

Does Neo4j Support the concept of views

I'm starting with Neo4J trying to migrate my current system from a Relational DB to Neo4j
and have a peculiar problem to overcome.
I have a table called Orders and has 2 particular columns that are being a pain.
ShipBy is a value for (Train/Air/Truck)
Carrier is the Id of the company carrying the order but this changes, if it ships by Air, it has something like UPS/ALASKA/CONTINENTAL; if it ships by Train, it has something like BNSF/KANSASCITYRAIL/ETC...
these values come from different catalog tables, so this was resolved in my system with something like this
Select Orders.Number, Carrier.Name from Orders, (Select 'T' Type,Id,Name from Truckers union all Select 'R' Type, Id, Name from RailCompanies union all Select 'A' Type, Id, Name from AirLines) Carriers
Where Orders.ShipBy = Carriers.Type and Orders.CarrierId=Carrier.Id
I'd appreciate any pointer on this.
Neo4J doesn't have views in the way that relational DBs have. There are several things you could do as alternates:
Continually re-issue the query that computes the "view" you need, as needed
Create a special "view node", and then link that node via relationships to all of the other nodes that would naturally occur in your "view". Querying your view then becomes as simple as pulling up that one "view node" and traversing your edges to the view results.
Option #1 is easiest, option #2 is probably faster, but comes with it the maintenance burden that as your underlying nodes in the DB change, you need to maintain your view and make sure it points to the right places.
As we can read here "In database theory, a view is the result set of a stored query on the data, which the database users can query just as they would in a persistent database collection object."
Neo4j doesn't host stored queries, but you could think to extend Neo4j Servers as posted here by Stefan: https://stackoverflow.com/a/21780942/3442366
Materialized views are of course different...
Rely on the power of relationship management offered by Neo4j ;-)
Cheers,
Lorenzo

DB2 : Optimization required for a query

I have to fetch data from DB2 database from a .NET in following way:
join 5 tables 2 inner join 3 left outer join
the data have to be written on a text file . so functions such as LPAD/RPAD, substr etc for formatting have to be used.
the data retrieved would be about 100000 rows
I am planning to create a view so that application gets rid of joins and i get required columns only in the view.
I want to know If formatting of data should also be moved to the definition of view? So that in the application I will perform only
select * from view
Please advice
Thanks
There is really no difference from the database engine's perspective whether the application submits a query with joins, text functions, etc or if all of these are contained within a view and the application executes a simple select * from view. DB2 compiles the query in exactly the same way.
The only "advantage" to using a view is convenience for the application developer. The disadvantage to putting the SQL statement into a view, of course, is that if the requirements change you'll have to modify the view.
As far as including the text formatting within the view: If this view will exist ONLY to support this one single application (and you're using it only for convenience), then it may make sense to include the formatting within the view definition. However, if other applications may have some need for the view (but not the text formatting), then keeping the formatting in your query against the view is the better choice.
As a DBA, I would suggest that the best place for text formatting is within your application code. Writing a formatted string using printf() (or equivalent) is something that applications are usually pretty good at.

Very slow search of a simple entity relationship

We use CRM 4.0 at our institution and have no plans to upgrade presently as we've spend the last year and a half customising and extending the CRM to work with our processes.
A tiny part of model is a simply hierarchy, we have a group of learning rooms that has a one-to-many relationship with another entity that describes the courses available for that learning room.
Another entity has a list of all potential and enrolled students who have expressed an interest in whichever course.
That bit's all straightforward and works pretty well and is modelled into 3 custom entities.
Now, we've got an Admin application that reads the rooms and then wants to show the courses for that room, but only where there are enrolled students.
In SQL this is simplified to:
SELECT DISTINCT r.CourseName, r.OtherInformation
FROM Rooms r
INNER JOIN Students S
ON S.CourseId = r.CourseId
WHERE r.RoomId = #RoomId
And this indeed is very close to the eventual SQL that CRM generates.
We use a Crm QueryEntity, a Filter and a LinkEntity to represent this same structure.
The problem now is that the CRM normalizes the a customize entity into a Base Table which has the standard CRM entity data that all share, and then an ExtensionBase Table which has our customisations. To Give a flattened access to this, it creates a view that merges both tables.
This view is what is used by the Generated SQL.
Now the base tables have indices but the view doesn't.
The problem we have is that all we want to do is return Courses where the inner join is satisfied, it's enough to prove there are entries and CRM makes it SELECT DISTINCT, so we only get one item back for Room.
At first this worked perfectly well, but now we have thousands of queries, it takes well over 30 seconds and of course causes a timeout in anything but SMS.
I'm given to believe that we can create and alter indices on tables in CRM and that's not considered to be an unsupported modification; but what about Views ?
I know that if we alter an entity then its views are recreated, which would of course make us redo our indices when this happens.
Is there any way to hint to CRM4.0 that we want a specific index in place ?
Another source recommends that where you get problems like this, then it's best to bring data closer together, but this isn't something I'd feel comfortable in trying to engineer into our solution.
I had considered putting a new entity in that only has RoomId, CourseId and Enrolment Count in to it, but that smacks of being incredibly hacky too; After all, an index would resolve the need to duplicate this data and have some kind of trigger that updates the data after every student operation.
Lastly, whilst I know we're stuck on CRM4 at the moment, is this the kind of thing that we could expect to have resolved in CRM2011 ? It would certainly add more weight to the upgrading this 5 year old product argument.
Since views are "dynamic" (conceptually, their contents are generated on-the-fly from the base tables every time they are used), they typically can't be indexed. However, SQL Server does support something called an "indexed view". You need to create a unique clustered index on the view, and the query analyzer should be able to use it to speed up your join.
Someone asked a similar question here and I see no conclusive answer. The cited concerns from Microsoft are Referential Integrity (a non-issue here) and Upgrade complications. You mention the unsupported option of adding the view and managing it over upgrades and entity changes. That is an option, as unsupported and hackish as it is, it should work.
FetchXml does have aggregation but the query execution plans still uses the views: here is the SQL generated from a simple select count from incident:
'select
top 5000 COUNT(*) as "rowcount"
, MAX("__AggLimitExceededFlag__") as "__AggregateLimitExceeded__" from (select top 50001 case when ROW_NUMBER() over(order by (SELECT 1)) > 50000 then 1 else 0 end as "__AggLimitExceededFlag__" from Incident as "incident0" ...
I dont see a supported solution for your problem.
If you are building an outside admin app and you are hosting CRM 4 on-premise you could go directly to the database for your query bypassing the CRM API. Not supported but would allow you to solve the problem.
I'm going to add this as a potential answer although I don't believe its a sustainable or indeed valid long-term solution.
After analysing the indexes that CRM had defined automatically, I realised that selecting more information in my query would be enough to fulfil the column requirements of an Index and now the query runs in less then a second.

Retrofitting record-level access restrictions in classic asp applications

Like the title says, I've been asked to come up with an estimate for retrofitting an existing asp application.
The current security mechanism controls access to different parts of the application (page-level restrictions), but has no mechanism for flagging individual records as restricted. Assigning rights to a user (using the existing, custom access management code) is no problem, but enforcing the rights is a different matter - each asp page has embedded sql - there's no use of stored procs, objects, etc.
Is the only solution to modify each table and query, or is there a better way? Any pointers, suggestions or prayers would be welcome.
This is classic asp, running on IIS6, against an oracle database.
Update: Here's a user scenario.
We have users, managers, directors, and VPs. The managers can see data created by users who report to them, but not users who report to other managers. Users can't see data created by any managers. Same thing with directors - they can see down, but their reports can't see up.
This sounds like an ideal time to implement row-level security. Oracle has a package DBMS_RLS that allows you to define arbitrary access policies that can be applied to one or more tables that limit what rows a particular user is allowed to see. Conceptually, when a user issues a query with no filters on a protected table, i.e.
SELECT *
FROM my_table
Oracle automatically and transparently inserts a WHERE clause defined by your security policy that limits the result set. You shouldn't need to make any changes to the SQL your application is executing.
Assuming you need maximum granularity, the ability to "grant" each and any row to any of very many users, then you have a many-to-many relation, yes?
So apply the following pattern:
Add a tables of users.
Then, for each restricted table, so the following:
Rename it tablename + "_base".
create a many-to-many table that
associates that table's id with a
user id, called tablename +
"allowed_user".
create a view with the name table
name that joins tablename_base to
table_name_allowed_user, with a
select* from tablename_base and
user_id from tablename_allowed_user.
This view should meet Oracle's
requirements rto be "inherently
updatable."
Now comes the hard part. You need to add "and user_id = $user_id" to every query. Find the various functions you're using to make queries. Wrap those function(s) in ones that gets the user id from the session and add that predicate.
One passable way to do this is to read select string, find the all "where"s (for subqueries there may be more that one), and replace it with "where (user = $user) and ". For queries that don't have a where, you'll need to insert this before any "group by" or "order by". This is fragile, so obviously you'll test that this works for all pages (you have an automated test for all pages, right?), and add hacks to cover special cases.
"update" statements won't have to change; "inserts" will presumably insert both to the view and then do a separate insert to the table's "allow_user" table with the id of the inserting user, to automatically grant teh inserting user acces to what he inserted.
If your number of users is more limited, or you're restricting types of users, you can go with a strategy of multiple views named for the user or type; then you'd replace tables names in the queries with the appropriate views.

Resources