Deleting the matching rows from the table - flask-sqlalchemy

I am developing an application which has python ,flask frontend and sqlalchemy is connectivity layer.I have a table called Studentdepartment which has three columns combo_id,student_id,department_id.
Here one or more students can be in one department. For example
combo_id student_id department_id
1 1 1
2 2 1
3 3 1
4 4 2
combo_id is the primary key.
Now I have to delete the rows which has the department_id is 1.
I have tried this query
delete_updated_department_id = db.session.query(Studentdepartment).filter(Studentdepartment.department_id==department_id).delete()
hint:I am fetching the department id from my script.
But I am getting this error
"Multiple rows were found for one()"
sqlalchemy.orm.exc.MultipleResultsFound: Multiple rows were found for one()
How should I delete all the rows which is matching with department id

First of all, I dont know why your code won't allow you to delete multiple rows, but if I remember correctly, the syntax below allows you delete multiple (all) rows that match the condition.
metadata = db.MetaData(bind=engine)
table_name = db.Table('Studentdepartment', metadata, autoload=True)
k = 'department_id'
v = department_id
query = table_name.delete()
query = query.where(getattr(table_name.c, k) == v)
my_session = Session(engine)
my_session.execute(query)
I'm using k, v here to easily expand the syntax with multiple conditions, but its not necessary here

Related

SQL - Update top n records for each value in column a where n = count of column b

I have one table with the following columns and sample values:
[test]
ID | Sample | Org | EmployeeNumber
1 100 6513241
2 200 3216542
3 300 5649841
4 100 9879871
5 200 6546548
6 100 1116594
My example count query based on [test] returns these sample values grouped by Org:
Org | Count of EmployeeNumber
100 3
200 2
300 1
My question is can I use this count to update test.Sample to 'x' for the top 3 records of Org 100, the top 2 records of Org 200, and the top 1 record of Org 300? It does not matter which records are updated, as long as the number of records updated for the Org = the count of EmployeeNumber.
I realize that I could just update all records in this example but I have 175 Orgs and 900,000 records and my real count query includes an iif that only returns a partial count based on other columns.
The db that I am taking over uses a recordset and loop to update. I am trying to write this in one SQL update statement. I have tried several variations of nested select statements but can't quite figure it out. Any help would save my brain from exploding. Thanks!
Assuming, that id is the unique ID of the row, you could use a correlated subquery to select the count of row IDs of the rows sharing the current organization, that are less than or equal to the current row ID and check, that this count is less than or equal to the number of records from that organization you want to designate.
For example to mark 3 records of the organization 100 you could use:
UPDATE test
SET sample = 'x'
WHERE org = 100
AND (SELECT count(*)
FROM test t
WHERE t.org = test.org
AND t.id <= test.id) <= 3;
And analog for the other cases.
(Disclaimer: I don't have access to Access (ha, ha, pun), so I could not test it. But I guess it's basic enough, to work in almost every DBMS, also in Access.)

SQL query to pull certain rows based on values in other rows in the same table

I have a set of data that contains 2 sets of identifiers: a unique number for that record, Widget_Number, and the original unique number for the record, Original_Widget_Number. Typically these two values are identical but when a record has been revised, the a new record is created with a new Widget_Number, preserving the old Widget_Number value in Original_Widget_Number. IE SELECT * FROM widgets WHERE Widget_Number != Original_Widget_Number returns all records that have been changed. (Widget_Number increments by 10 for new widgets and by 1 for revised widgets.)
I would like to return all records that were changed as well as the original records related to those records. For example if I had a table containing:
Widget_Number Original_Widget Number More_Data
1: 10 10 Stephen
2: 11 10 Steven
3: 20 20 Joe
I would like a query to return rows 1 & 2. I know I could loop trough this in a higher-level language but is there a straightforward way to do this in MS SQL?
using exists():
select *
from widgets as t
where exists (
select 1
from widgets as i
where i.original_widget_number = t.original_widget_number
and i.widget_number != i.original_widget_number
)
or in()
select *
from widgets as t
where t.original_widget_number in (
select i.original_widget_number
from widgets as i
where i.widget_number != i.original_widget_number
)
The following should get both the records that have changed and the original records:
select w.*
from widgets w
where w.widget_number <> w.original_widget_number or
exists (select 1
from widgets w2
where w.widget_number = w2.original_widget_number and
w2.widget_number <> w2.original_widget_number
);
select * from widget
where original_widget_number in
(select original_widget_number from widget
where widget_number <> original_widget_number)

The MIN() Function Ms Access

this is a sample sql query that i created ms access query. i am trying to get only one row the min(DATE). how ever when i run my query i get multiple lines. any hits? thanks
SELECT tblWarehouseItem.whiItemName,
tblWarehouseItem.whiQty,
tblWarehouseItem.whiPrice,
Min(tblWarehouseItem.whiDateIn) AS MinOfwhiDateIn,
tblWarehouseItem.whiExpiryDate,
tblWarehouseItem.whiwrhID
FROM tblWarehouseItem
GROUP BY tblWarehouseItem.whiDateIn,
tblWarehouseItem.whiItemName,
tblWarehouseItem.whiQty,
tblWarehouseItem.whiPrice,
tblWarehouseItem.whiExpiryDate,
tblWarehouseItem.whiwrhID;
If i have my sql code like that is working as it should:
SELECT MIN(tblWarehouseItem.whiDateIn) FROM tblWarehouseItem;
In the first query, you group by a number of columns. That means the minimum value will be calculated for each group, which in turn means you may have multiple rows. On the other hand, the second query will only get the minimum value for the specified column from all rows, so that there is only one row in the result set.
A simple example is shown below to illustrate the above.
Table:
Key Value
1 1
1 2
2 3
2 4
On Group By Key:
GroupKey MinValue
1 = min(1,2) = 1 -> Row 1
2 = min(3,4) = 3 -> Row 2
On Min (Value)
MinValue
=min(1,2,3,4) = 1 -> Row 1
For a table like above, if you want to select all rows and also show the minimum value from whole table rather than per group, you can do something like this:
select key, (select min(value) from table)
from table
SELECT WI.*
FROM tblWarehouseItem AS WI INNER JOIN (SELECT whiimtID, MIN(tblWarehouseItem.whiDateIn) AS whiDateIn
FROM tblWarehouseItem
GROUP BY whiimtID) AS MinWI ON (WI.whiDateIn = MinWI.whiDateIn) AND (WI.whiimtID = MinWI.whiimtID);

Sql Query to get number of floors

I am working on a hotel management software and I need to display floors and the rooms on that floor......
I have a wing_master table in the database with following columns -:
wing_id,
wing_name,
floor,
floor_room_count,
status
Its like I have a record for one wing in that hotel which has 4 floors, but when I write a query to get the floors in that wing it just gives me "4" as the result in sql.....
I want the query to return it as follows -:
1
2
3
4
I want it this way so that I can use nested data-list control in asp.net....
My query is "select floors from wing_master where wing_id = 1"
For most databases (not MySQL), you can use a recursive query to obtain all floors:
with all_floors as (
select floors from wing_master where wing_id = 1
union all
select floors - 1 as floors from all_floors
where floors > 1
)
select * from all_floors order by floors;
SQLFiddle example.
In MySQL, the easiest way would be to create a numbers table that has a sequence of numbers up to the highest possible floor. Then join to that table to get all floors:
select num from wing_master
join numbers on
wing_id = 1 and
num <= floors;
SqlFiddle example.
Your query is ok, and also it seems that query and table structure will be fulfilling your requirements. can you show your data, because as per the structure, there should be four rows in the table, showing floor 1, 2, 3, 4
something like this
floor wing_id
1 1
2 1
3 1
4 1
If that is how your data looks, then your query must be ok, else there is some other issue. so do share your structure with few rows of data.

Get specific "version" of a column

I have an app that uses SQLite to store data locally. There may be more than one file storing the data. All the files contain a list of items, but only one of them has the "correct" status for the current user (basically, there is a "user" db in $HOME and a "system-wide" one in /etc).
Usually, both files will contain the same list of items, and only the status column will differ. If, however, either contains items not in both, I want that data as well.
SQLite does not have FULL OUTER JOIN.
A solution I have come up with is this:
SELECT item, group_concat(status) AS status FROM (SELECT item,status FROM items UNION SELECT item,status FROM otherdb.items) GROUP BY item;
And then parsing the comma-separated "status" output to get the "right" status. I would like a pure SQL solution, however.
The values I want for status are:
If any = 1, status = 1
elif any = -1, status = -1
elif any = 2, status = 2
elif any = -2, status = -2
else status = 0 or NULL
status may only (in the db) be -2,-1,0,NULL,1,2 so this covers all data.
If there is a solution that only gives whichever one is non-zero and non-null, that could work too, although I would prefer the above.
I would sugest you one approach:
1. create a temp table, one adittional column for a flag "otherbd";
2. throw everything from the 2 tables in there;
3. delete the lines you don't want;
Create a status priority table with the following values
status priority
1 5
-1 4
2 3
-2 2
0 1
NULL 0
The concept is to join your two tables against this StatusPriorty table, Group the records and use MAX(Priority) to get your results