Database Relation source depending on field - mysql

I have a database of projects and their parent companies that manage them, each project and company has lists of departaments and countries.
However if project has field DEFAULT set to true, the list of dep/ countries should be loaded from its parent company instead.
My question is what would be the best method to design this ? Is it possible to do it "correctly" in MySQL or should i just manage it in application code (not too good).

You can use a conditional expression in your join criteria. For example, using MySQL's IF() function:
JOIN departments ON departments.departmentID = IF(projects.default,
company_departments.departmentID,
projects_departments.departmentID
)

Related

I want to enable display or hide in my mysql table

This is my table. I need user to be able to be enable to either show or hide these attributes in their profile. For eg. a user might want to see city in profile but not the country. How do I do this without changing the structure of this table.
I'd say this is more of a front-end problem (rather than back-end)... One way you could perhaps solve this is to retrieve all data you need from the database for the selected user, and show a subset of the user data (that most users will likely want to see - name, age, favourite food etc)
Then you could use something like jQuery to power a 'Show more' toggle which will show/hide and give you the rest of the info.
SELECT a.*
, b.*
FROM contacts a -- assuming this is what your table is called
LEFT JOIN attributes b -- guessing that's the name of your example table
ON ( a.contact_id = b.contact_id )
WHERE a.contact_id = :contact_id -- bind variable
I would refrain from using the asterisk (*) in favour of just selecting the columns you need (you can write appropriate indexes and speed up the SQL this way).
If you've got a ton of data about a user (more than just basic stuff such as their name and some simple attributes) - then you might want to adopt a similar approach to above - but only retrieve the additional data you need if a user clicks 'Show more'.

Unique records in search query including many to one subquery

First time poster and enthusiastic Access newbie.
I've got a search screen based on Allen Browne's wonderful search in vba (http://allenbrowne.com/ser-62.html). This has worked great for most of my purposes, but now a child table is duplicating records.
Our clients(providers), can be enrolled in multiple programs. we've got four. I want a search that let's me filter by provider type, but not create duplicate records when a provider is enrolled in more than one provider type. In the example image, carmen titus is in the LEHRC and fccn programs, and therefore shows up twice. Tried to post pic but no dice.
Please help! I searched diligently and could not find a solution. I'd appreciate the support or to be pointed to a related post. I hope this makes sense. I think half my battle as a self-trained newbie is not knowing the terminology.
We'll need more info!
It sounds like the query you are basing the search on contains columns from two tables with a one to many relationship ie clients and "Client programs", such that a single client has zero to 4 programs.
It sounds like you only want to return a list of providers (ie rows on the one side), but your SQL is returning data from both tables.
Here's what you SQL might need to look like to do what you need:
SELECT *
FROM clients AS mainClient
WHERE
EXISTS
(SELECT 1
FROM clients AS C
LEFT JOIN ClientPrograms AS CP
ON C.ID = CP.ClientID
WHERE mainClient.ID = C.ID
' the above line links the EXISTS "Sub query" to the main query
AND client name like "*j*" ... etc...
... ie lots of criteria generated by you popup search criteria dialogue)
)
By adding the EXISTS statement the main query will be editable.
If you had used SQL like the following you would not be able to edit it
SELECT c.name, c.dob, etc.. ie all the field you want on the form whichwill all be from the client table
FROM clients AS C
LEFT JOIN ClientPrograms AS CP
ON C.ID = CP.ClientID
WHERE mainClient.ID = C.ID
' the above line links the EXISTS "Sub query" to the main query
AND client name like "*j*" ... etc...
... ie lots of criteria generated by you popup search criteria dialogue)
GROUP BY all the field in the select statement
I hope this gives you some inspiration

How can I allow users sql access to a table limited to certain rows?

I'm building an stock exchange simulation game. I have a table called 'Market_data' and in the game players simulate being in particular dates and are allowed to use SQL queries to retrieve the historical data and plan their course of action. My difficulty is that I need to limit the rows they can access based on the current date they are playing on so they cant see rows with a date greater than the current date.
Eg: An user is running the game and is currently in the year 2010, if he does a simple select like "SELECT * FROM market_data" I don't want him to see rows with Date > 'x-x-2010'
The only soution that I know of is to parse the user's SQL and add WHERE clauses to remove newer dates but it seems time consuming and prone to errors and I wasn't sure whether there were better alternatives. Any ideas on how to do this right will be thanked.
Solution is SQL Views, Views are used for several different reasons:
*1.*To hide data complexity. Instead of forcing your users to learn the T-SQL JOIN syntax you might wish to provide a view that runs a commonly requested SQL statement.
*2.*To protect the data. If you have a table containing sensitive data in certain columns, you might wish to hide those columns from certain groups of users. For instance, customer names, addresses and their social security numbers might all be stored in the same table; however, for lower level employees like shipping clerks, you can create a view that only displays customer name and address. You can grant permissions to a view without allowing users to query the underlying tables. There are a couple of ways you might want to secure your data:
a.Create a view to allow reading of only certain columns from a table. A common example of this would be the salary column in the employee table. You might not want all personnel to be able to read manager's or each other's salary. This is referred to as partitioning a table vertically and is accomplished by specifying only the appropriate columns in the CREATE VIEW statement.
b.Create a view to allow reading only certain rows from a table. For instance, you might have a view for department managers. This way, each manager can provide raises only to the employees of his or her department. This is referred to as horizontal partitioning and is accomplished by providing a WHERE clause in the SELECT statement that creates a view.
*3.*Enforcing some simple business rules. For example, if you wish to generate a list of customers that need to receive the fall catalog, you can create a view of customers that have previously bought your shirts during the fall.
*4.*Data exports with BCP. If you are using BCP to export your SQL Server data into text files, you can format the data through views since BCP's formatting ability is quite limited.
*5.*Customizing data. If you wish to display some computed values or column names formatted differently than the base table columns, you can do so by creating views.
reference taken from http://sqlserverpedia.com.
1)You can use mysql proxy http://dev.mysql.com/downloads/mysql-proxy/ with custom rules restricting access.
2)You can use stored procedures/functions
3)You can use views
The basic way would be :
-> Prevent that user (or group) from accessing the base table.
-> Define a view on top of that table that shows only the rows these users are supposed to see.
-> Give those users SELECT permission on the view.
-> And you can also use SQL Encryption,Decryption and Hashing concept.
Encryption & Decryption examples can be found here:
http://msdn.microsoft.com/en-us/library/ms179331.aspx
Hashing example can be found here:
http://msdn.microsoft.com/en-us/library/ms174415.aspx

Column name collision in SQL Server view joining database architecture

First of all, sorry the way I write, bad English here.
Please, consider the following scenario:
I made my database architecture combining views as such:
Entity City has the columns { city_id, city_name, state_name, ... }
Entity User has the columns { user_id, user_name, user_login, city_id, ... }
Each entity has a view, the city view does not have FK to any other entity, so its a simple select.
User entity have one FK to city entity, so it makes a join with the city entity in the view.
As the following example:
create view vw_user as
select user.user_id,
user.user_name,
user.user_login,
vw_city.*
from user (nolock)
inner join vw_city (nolock) on vw_city.city_id = user.city_id
go
So if you have an entity like user_access with a FK to user, the view of user_access will have an inner join to vw_user, and it will bring up all the columns from user and city entities.
In the end, I just make a query on the view, and it returns the full entity with all the foreign references.
This works great, and make the maintenance procedures very easier, I have a stored procedure that recompile all the views if any change is needed to one of the entities.
But, it has a problem, and I discovered this in a very bad situation, the system that uses this architecture is working very fast and smooth already, and I need to join two entities that share the entity city for example, so it generates a collision of columns, SQL Server does not allow this in views, you can execute a query with collision with no problem, but you can't do it in a view.
So, this is my problem, I need to find a way to fix this, but I can't find an answer to it myself.
The only thing I ended up doing is making a hard-coded view with the columns renamed.
But I want a solution for the entire architecture, something permanent, like an upgrade.
This architecture is followed in code, with C#, so there is a dependence on the column names.
When I read the data from the query, I need to get the data from the column name, so this code can be reused with other classes, doing the same thing that the view does in the query, in the c# code.
So, getting data with ordinal is out of the question.
Any ideas?
Thanks, and sorry, but this is very hard to describe.
Well, just to close the subject, as SMC suggested i have used aliases to identify the columns and the tables in my queries.
So the query looks like this now - using the example from the topic:
Select 1.user_id as 1,
1.user_name as 2,
1.user_login as 3,
1.city_id as 4,
2.city_id as 5,
2.city_name as 6,
2.state_name as 7
from user as 1
inner join city as 2 on 2.city_id = 1.city_id
Just notice the columns 4 and 5, they will not collide now :)
Wen my application makes this query he also make the Classes involved to know their aliases in the current query.
It works fine, solved my problem and i don't need to use views anymore.
In the end, the application is faster then before.
That's it :) hope it helps anybody out there.
It's because the Column Name in each View or Function must be unique. You need to be specific while selecting the column Names. Use Alias and then refer the column Names.
You tried to create VIEW using a single column name more than once in the statement.
Remove * and give explicit column name

Joining a table stored within a column of the results

I want to try and keep this as one query and not use PHP, but it's proving to be tough.
I have a table called applications, that stores all the applications and some basic information about them.
Then, I have a table with all the types of applications in it, and that table contains a reference to another table which stores more specific data about the specific type of application in question.
select applications.id as appid, applications.category, type.title as type, type.id as tid, type.valuefld, type.tablename
from applications
left join type on applications.typeid=type.id
left join department on type.deptid=department.id
where not isnull(work_cat)
and work_cat != ''
and applications.deleted=0
and datei between '10-04-14' and '11-04-14'
order by type, work_cat
Now, in the old version, there is another query on every single result. Over hundreds of results... that sucks.
This is the query I'd like to integrate so I can get all the data in one result row. (Old is ASP, I'm re-writing it in PHP)
query = "select sum("&adors.fields("valuefld")&") as cost, description from "&adors.fields("tablename")&" where appid = '"&adors.fields("tablename")&"'"
Prepared statements, I'm aware, are the best solution, but for now they are not an option.
You can't do this with a plain SQL query - you need to have a defined set of tables that your query is based on. The fact that your current implementation queries from whatever table is named by tablename from the first result-set means that to get this all in one query, you will have to restructure your data. You have to know what tables you're querying from rather than having it dynamic.
If the reason for these different tables is the different information stored in each requiring different record (column) structures, you might want to look into Key/Value pair storage in a large table. Once you combine the dynamically named ones into a single location you can integrate your two queries together.