Complex SQL queries (DELETE)? - sql

I'm working with three tables, and for simplicity's sake let's call them table A, B, and C. Both tables A and B have a column called id, as well as one other column, Aattribute and Battribute, respectively. Column c also has an id column, and two other columns which hold values for A.id and B.id. Now, in my code, I have easy access to values for both Aattribute and Battribute, and want to delete the row at C, so effectively I want to do something like this:
DELETE FROM C WHERE aid=(SELECT id FROM A WHERE Aattribute='myvalue') AND bid=(SELECT id FROM B WHERE Battribute='myothervalue')
But this obviously doesn't work. Is there any way to make a single complex query, or do I have to run three queries, where I first get the value of A.id using a SELECT with 'myvalue', then the same for B.id, then use those in the final query?
[Edit: it's not letting me comment, so in response to the first comment on this: I tried the above query and it did not work, I figured it just wasn't syntactically correct. Using MS Access, for what it's worth. ]

You must use IN instead of =.
DELETE
FROM C
WHERE aid IN
(SELECT id
FROM A
WHERE Aattribute='myvalue'
)
AND bid IN
(SELECT id
FROM B
WHERE Battribute='myothervalue'
)

Related

BigQuery: Select column if it exists, else put NULL?

I am updating a daily dashboard. Assume everyday I have two tables TODAY and BEFORE_TODAY. What I have been doing daily was something like:
SELECT a, b FROM TODAY
UNION ALL
SELECT a,b FROM BEFORE_TODAY;
TODAY table is generated daily and is appended to all the data before it. Now, I need to generate a new column say c and in order to UNION ALL the two, I need that to be available on BEFORE_TODAY as well.
How can I add a conditional statement to BEFORE_TODAY to check if I have a c column and use that column, else use NULL instead of it.
Something is wrong with your data model. You should be putting the data into separate partitions of the same table. Then you would have no problems. You could just query the master table for the partitions you want. The column would appear in the history, with a NULL value.
That is the right solution. You can create a hacked solution, assuming that your tables have a primary key. For instance, if a, b is unique on each row, you could do:
select t.a, t.b, t.c
from today t
union all
select b.a, b.b,
(select c -- not qualified on purpose
from before_today b2
where b2.a = b.a and b2.b = b.b
) as
from before_today b cross join
(select null as c) c;
If b.c does not exist, then the subquery returns c.c. If it does exist this it returns b2.c from the subquery.
Although by combining dynamic SQL and INFORMATION_SCHEMA, you can write a script to achieve what you told, this doesn't seems to be the right thing to do.
As part of your data model planning, you should add column c to BEFORE_TODAY ahead of time. The newly added column on existing rows will always have NULL value. Then you can add column to TODAY and reference column c as normal.

How to populate query with result from different table?

I have two tables. Table A and table B. Table A has a column that is a reference to the primary key to table B. I want to run a select query on table A and then populate the column that referrers to B with all of the data in that row of B.
SELECT * from A a LEFT JOIN B b ON a."b_id" = b."id" WHERE ...
That gives a result with each row containing all of the columns of A and all of the columns of B. It is a confusing mess to figure out which column is from which table. I want to be able to do something like.
row.A."column name"
row.B."column name"
I don't want to have to rename every single column using AS. There must be a better way to do this.
Not a 100% sure what your asking but what I think your asking is.
You want a way to have only column B values to show? If so you could do:
SELECT B.*
FROM A
JOIN B
ON A.b_id = B.id
That will only get you the B columns and data, If you want A also maybe do but you want to have it separate from b maybe do:
SELECT B.*,'|' AS ['|'], A.*
FROM A
JOIN B
ON A.b_id = B.id
Hopefully this is helpful, if not to you maybe another reader.

Why do I receive different results in an Access query when the order of the columns is different with a distinct clause?

Exactly as the title says.
I have an MS Access database. I didn't create it, I was handed it with a request to update a query. My task was to add a column with a calculated result, and we added a new column... essentially lets say we have query:
SELECT DISTINCT a, b, c
FROM tbl1
Modified with a UDF to be:
SELECT UDF(d) as e, *
INTO tb2
FROM
(SELECT DISTINCT a, b, c, d FROM tbl1)
We did this, and got different answers, 3 more rows out of hundreds of thousands. I assumed simply that column d must contain more information and after removing duplicates by the DISTINCT clause we ended up with more columns.
In attempting to verify this, we discovered that the order of the columns seemed to matter. If we did this:
SELECT UDF(d) as e, *
INTO tb2
FROM (SELECT DISTINCT a, c, b, d FROM tbl1)
The extra columns went away.
I thought at first that I was using distinct wrong, but checking different syntax combinations resulted in errors, and looking up the SQL documentation for access said that this was correct. A colleague suggested that we needed a GROUP BY clause but since we're not doing any aggregation and we want the globally unique records that doesn't seem to fit.
What am I missing?

Is exist a simple way to select all data from specific table

I have two tables: A, B. I need to select all data from B.
I could do this like
SELECT id, b1, b2, ... b20 FROM A,B WHERE A.id = B.id;
it's not cool solution. I will need to update this statement if I modify B's database. Is exist something like ?
SELECT *(B)
It selected all data from B and didn't selected any data from A.
My databases
A
id
a1
a2
...
a20
B
id
b1
b2
...
b20
So if you want create database seriously you shouldn't see on complexity of way but on efficiency and speed. So my advice to you is use JOIN that is the best solution for selecting data from two and more tables, because this way is fast as possible, at least for my more cleaner like for example inserted select.
You wrote: I need to select all data from B this means SELECT * FROM B not that you wrote.
My advice to your is using this:
SELECT * FROM A <INNER / LEFT / RIGHT / NATURAL> JOIN B ON A.id = B.id;
or to select specific columns
SELECT A.column1, A.column2, ... FROM A <INNER / LEFT / RIGHT / NATURAL> JOIN B ON A.id = B.id;
Note:
NATURAL JOIN will work in above example since the primary key
and the foreign key in the two tables have the same name. So you must be very
careful in using NATURAL JOIN queries in the absence of properly
matched columns.
So you really should think about how you will create database and how you will working with database, how you will pulling data for View from database, how you will insert new potential data to database etc.
Regards man!
Use following query:
SELECT * FROM B;
or
SELECT * FROM B INNER JOIN A ON A.id = B.id;
if you want to join tables A and B.
I suspect that the others have sufficiently answered your question about selecting all fields from table B. That's great, as you really should understand the SQL basics. If they haven't, I'd also advise that you check out SQLite.org site for a clarification on SQL syntax understood by SQLite.
But, assuming you've answered your question, I just want to voice two words of caution about using the asterisk syntax.
First, what if, at some later date, you add a column to B that is a big hairy blob (e.g. a multimegabyte image). If you use the * (or B.*) syntax to retrieve all of the columns from B, you may be retrieving a ton of information you might not need for your particular function. Don't retrieve data from SQLite if you don't need it.
Second, is your Objective C retrieving the data from your select statement on the basis of the column names of the result, or based upon the index number of the column in question. If you're doing the latter, then using the * syntax can be dangerous, because you can break your code if the physical order of columns in your table ever changes.
Using named columns can solve the problem of memory/performance issues in terms of retrieving too much data, as well as isolating the Objective C from the physical implementation of the table in SQLite. Generally, I would not advise developers to use the * syntax when retrieving data from a SQL database. Perhaps this isn't an issue for a trivial project, but as projects become more complicated, you may want to think carefully about the implications of the * syntax.
I don't know if the following query would work in sqlite, I know it works in Oracle, but you can give it a try...
SELECT B.* FROM A,B WHERE A.id = B.id;

PostgreSQL libpq: PQNumber and column aliases

In a Postgres libpq sql there is a function PQfnumber: Returns the column number associated with the given column name.
Lets say I have a select:
select a.*, b.* from a, b where a.id = b.id
now if I will call
number = PQfnumber(pgresult, "a.id");
it will return -1.
Correct way is to call:
number = PQfnumber(pgresult, "id");
which returns position of a.id. So how would I need to call the function to get column number of b.id?
The only way around it seems to write a different select:
select a.id as a_id, a.*, b.id as b_id, b.* from a, b where a.id = b.id
number = PQfnumber(pgresult, "b_id");
Any other way around this?
No, you've found the right way.
Of course, with a.id = b.id in an inner join (as in the example code), why would you care which column you were looking at? Also, there are good reasons not to have just an id column as the primary key of every table. Even if a lot of tables have single-column integer keys, if you consistently name columns which hold a primary key to a given table, terser and more efficient syntax like JOIN ... USING is available.
If you use construct like this:
number = PQfnumber(pgresult, "a.id");
then you're query should contain a column alias like this:
SELECT a.id AS "a.id", b.* FROM a, b WHERE a.id = b.id;
You do have ambiguity in your code, should you tried such query in the PL/pgSQL language, you would have received the 42702: ambiguous_column exception.
I see the only way out here — you should give unique aliases for all the ambitious columns of your query. In fact, it is a good practice to give aliases for all columns, I always do so.