A、B两张表 获取过滤条件后A表中除了B表中剩余的数据

A表中有一定量的数据, B表中有一定量的数据, 当B表中某些字段值和A表中的字段值一样时即认为这两条数据一致, 剔除A表中所有和B表中数据一致的记录,得出来A表独有的记录。

 博客中主要用到的是exists关键字。先写sql语句:

not exists:

Select * from response_data p where not exists (

 select 1 from request_data q 

where p.idno=q.idno and p.create_date=q.create_date and p.type=q.type and q.type=0 AND p.result=q.result  AND q.result=0);


not in:

SELECT * FROM response_data p WHERE p.idno NOT IN  (

SELECT q.idno FROM request_data q 

WHERE p.idno=q.idno  and p.create_date=q.create_date and p.type=q.type and q.type=0 AND p.result=q.result  AND q.result=0 );


---------以下为业务逻辑:

业务逻辑:

Request_data表中的数据是,公司调用收费接口的记录,收费接口有两种(type=0,1,调用结果(result=0,1);

Response_data表中的数据是,公司要求收费的一方(type=0),返回给我们的一份数据,用于公司对账(看看有没有出现,我们没有 调用他们的接口,但是他们有记录的数据, 他们有记录且调用成功的就会收费)。

 

由于是公司对账, 所以只需要查出来接口方提供的数据中我们表中没有的记录即可(这些记录就是多收费的记录,对于我们有记录但是接口方没有的记录,由于不需要我们付费,所以就不用理会这部分数据)。

最终数据=Response_data - Request_date


Request_date 表的数据:



Response_data 表的数据:



条件: Idno相同,日期相同, 接口方相同, 请求结果相同

Select * from response_data p where not exists

( select 1 from request_data q where p.idno=q.idno and p.create_date=q.create_date and p.type=q.type and q.type=0 AND p.result=q.result  AND q.result=0);

直接执行该语句, 则会返回Response_data表的所有数据,从数据可以 看出,7request的数据有4条, 调用接口方0,的有三条, 成功的有一条。但是这条数据的id并不等于response_data中的数据(即,接口方没有记录我们的这次成功请求,开心吧, 不用付费就用了他们的服务),也就是说,接口方多收了我们2条数据的费用。

 

SELECT * FROM response_data p WHERE p.idno NOT IN  (SELECT q.idno FROM request_data q WHERE

p.idno=q.idno  and p.create_date=q.create_date and p.type=q.type and q.type=0 AND p.result=q.result  AND q.result=0 );


<think>我们计划使用C语言实现一个基于通用链的航空订票系统,包含订票和退票功能。根据引用内容,我们需要设计航班信息和订票信息的数据结构,并实现链存储。同时,系统需要支持数据持久化(保存到文件)和友好的交互界面。 设计思路: 1. 使用链存储航班信息和订票信息,因为链可以动态增长,适合不确定数据量的场景。 2. 设计通用链结构,可以用于存储不同类型的节点(航班节点、订票节点等)。 3. 实现航班管理(添加、修改、删除、查询)、订票、退票等功能。 4. 将链数据保存到文件中,以便下次启动时加载。 由于C语言没有泛型,我们可以通过以下方式实现通用链: - 链节点包含一个void*指针,指向实际数据,同时包含一个类型标识符。 - 或者,我们可以为每种数据类型分别定义链节点结构,但这样会导致代码重复。 这里我们采用第一种方式:设计一个通用的链节点结构,可以存储任意类型的数据。 但是考虑到实际系统中,航班信息和订票信息是两种不同的结构,且操作方式不同,我们也可以分别建立两个链:航班链和订票链。这样更简单直接。 根据引用[3],航班信息包括: 终点站名、航班号、飞机号、飞行周日(星期几飞行)、起飞时间、航班票价、票价折扣、乘员定额、余票量、已订票的乘客名单(链)以及等候替补的客户名单(队列)。 订票信息(乘客名单)包括: 订单编号、乘客姓名、证件号、订票额、航班号、座位号等。 由于系统需要支持候补功能,我们可以为每个航班维护一个候补队列(使用队列数据结构)。 因此,我们设计以下数据结构: 1. 航班信息(Flight): - 终点站(dest) - 航班号(flight_number) - 飞机号(plane_number) - 飞行周日(week_day,可以用整数示星期几,0示星期日,1-6示周一到周六) - 起飞时间(departure_time,可以用字符串如"08:00") - 票价(price) - 折扣(discount) - 总座位数(total_seats) - 剩余票量(remaining_seats) - 已订票乘客链(passenger_list) // 存储订票信息(Passenger)的链 - 候补队列(wait_list) // 存储候补乘客(WaitPassenger)的队列 2. 订票信息(Passenger): - 订单编号(booking_id) - 乘客姓名(name) - 证件号(id_number) - 订票数量(ticket_count) - 航班号(flight_number) // 冗余存储,方便查找 - 座位号(seat_number) // 可以是一个数组,但简单起见,我们可以记录起始座位号,或者不记录具体座位,只记录数量 3. 候补乘客信息(WaitPassenger): - 乘客姓名(name) - 证件号(id_number) - 需要的票数(ticket_count) 注意:引用[3]中要求,退票时要根据订单编号和姓名办理退票,然后检查候补队列。 链设计: - 航班链:链节点包含一个Flight结构,以及指向下一个节点的指针。 - 订票链:实际上,订票信息已经挂在航班结构的乘客链上,但我们也可以单独维护一个全局的订票链,方便按订单号查询。这里为了简单,我们选择每个航班的乘客链只存储该航班的乘客。退票时,我们需要根据订单号找到航班,然后从该航班的乘客链中删除。因此,我们需要一个全局的航班链,然后通过航班链找到对应航班的乘客链。 另一种设计:将所有的订票记录放在一个全局链中,这样在退票时可以直接查找。但这样会失去航班与乘客的关联,所以我们需要在订票记录中存储航班号,然后通过航班号找到航班,从而更新航班的剩余票量等。 综合考虑,我们采用以下设计: - 全局航班链(flight_list):存储所有航班。 - 每个航班结构内部有一个乘客链(passenger_list),存储该航班的所有订票记录。 - 全局的候补队列我们放在航班结构内部,即每个航班一个候补队列。 这样,当我们要退票时,先根据订单号(或乘客姓名)在哪个航班?我们可以遍历航班链,然后在每个航班的乘客链中查找。但这样效率低。因此,我们可以考虑增加一个全局的订票链(booking_list),存储所有订票记录(包括航班号),这样退票时先根据订单号在全局订票链中找到订票记录,然后根据航班号找到航班,再更新航班信息。 但是引用[3]要求退票时提供订单编号和姓名,所以我们设计退票函数时,输入参数为订单编号和姓名(用于验证)。因此,我们需要一个全局的订票链,用于快速查找订单。 因此,我们设计三个链: - 航班链(flight_list) - 全局订票链(booking_list) // 存储所有航班的订票记录 - 每个航班的候补队列(使用队列,可以用链实现) 注意:订票记录同时存在于全局订票链和对应航班的乘客链中。这样在退票时,我们既可以从全局订票链快速找到订票记录,又可以通过航班链找到对应的航班来更新剩余票量和处理候补队列。 但是,这样会导致数据冗余,需要注意数据一致性。 为了避免数据冗余,我们可以只保留一个全局订票链,而航班结构中的乘客链可以不要。当需要查找某个航班的所有订票记录时,遍历全局订票链,根据航班号过滤。这样效率较低,但节省空间。考虑到航班数量不多,订票记录也不会太多,可以接受。 因此,我们决定: - 航班结构(Flight)中不再包含乘客链,只包含剩余票量。 - 全局订票链(booking_list)存储所有订票记录,每个订票记录包含航班号。 - 每个航班仍然需要有一个候补队列(wait_list),因为候补队列是按航班区分的。 那么,如何获取某个航班的订票记录?我们可以遍历全局订票链,根据航班号来筛选。这样在退票时,我们只需要在全局订票链中删除记录,并更新对应航班的剩余票量,然后处理该航班的候补队列。 因此,数据结构设计如下: 1. 订票记录(Booking): typedef struct Booking { char booking_id[20]; // 订单编号 char flight_number[10]; // 航班号 char passenger_name[50]; // 乘客姓名 char id_number[20]; // 证件号 int ticket_count; // 订票数量 // 可以加上状态标志,如有效、已退票等,但这里我们简化,退票就删除 } Booking; 2. 候补乘客(WaitPassenger): typedef struct WaitPassenger { char passenger_name[50]; char id_number[20]; int ticket_count; // 需要的票数 } WaitPassenger; 3. 航班信息(Flight): typedef struct Flight { char dest[50]; // 终点站 char flight_number[10]; // 航班号(唯一) char plane_number[20]; // 飞机号 int week_day; // 0-6,0示星期日 char departure_time[10]; // 格式如"08:00" float price; // 票价 float discount; // 折扣 int total_seats; // 总座位数 int remaining_seats; // 剩余票量 // 候补队列:用链实现的队列 struct WaitPassengerNode { WaitPassenger data; struct WaitPassengerNode* next; } *wait_list; // 队头指针 } Flight; 4. 链节点结构: 由于航班链和订票链需要不同的数据类型,我们分别定义节点类型: - 航班链节点: typedef struct FlightNode { Flight data; struct FlightNode* next; } FlightNode; - 订票链节点: typedef struct BookingNode { Booking data; struct BookingNode* next; } BookingNode; - 候补队列节点(已经在Flight结构内部定义,即WaitPassengerNode) 5. 全局变量: FlightNode* flight_list = NULL; // 航班链头指针 BookingNode* booking_list = NULL; // 订票链头指针 功能实现: 1. 航班管理: - 添加航班:输入航班信息,创建Flight,插入flight_list。 - 修改航班:根据航班号查找,修改航班信息(注意:修改总座位数时,剩余座位数也要相应调整,但不能小于已订票数)。 - 删除航班:只能删除没有订票记录的航班(即该航班的订票记录在booking_list中不存在)。 - 查询航班:按终点站查询,遍历flight_list输出。 2. 订票功能: - 输入航班号、乘客信息、订票数量。 - 查找航班,如果剩余座位>=订票数量,则创建订票记录(生成唯一订单号),插入booking_list,更新航班的剩余座位。 - 如果剩余座位不足,则询问是否加入候补队列。若用户同意,则创建WaitPassenger并加入航班的wait_list(队尾)。 3. 退票功能: - 输入订单编号和乘客姓名(用于验证)。 - 在booking_list中查找该订单,验证乘客姓名。 - 如果找到,则删除该订票记录,并更新对应航班的剩余座位(增加退票数量)。 - 然后,检查该航班的候补队列(wait_list): 从队头开始,检查每个候补乘客的需求是否小于等于当前剩余座位。 如果满足,则为该乘客订票(创建订票记录,更新剩余座位),并将该乘客移出候补队列。 然后继续检查下一个队头,直到队头乘客的需求不满足或队列为空。 注意:订单编号需要唯一,我们可以设计一个生成规则,比如航班号+顺序号,或者时间戳等。 文件存储: - 航班数据存储:将flight_list链中的每个航班信息写入文件。 - 订票数据存储:将booking_list链中的订票记录写入文件。 - 候补队列:由于候补队列是临时性的,我们可以选择不保存,或者保存后下次启动时重新处理(但可能已经过期),所以这里我们不保存候补队列。 代码结构: 1. 定义数据结构(如上)。 2. 函数声明: - 航班管理函数: FlightNode* add_flight(Flight flight_data); int modify_flight(char* flight_number, Flight new_data); int delete_flight(char* flight_number); Flight* find_flight_by_number(char* flight_number); void search_flights_by_dest(char* dest); // 按终点站查询 - 订票函数: int book_ticket(char* flight_number, char* passenger_name, char* id_number, int ticket_count); // 返回订单号(或0示失败) - 退票函数: int cancel_ticket(char* booking_id, char* passenger_name); - 文件操作: void save_flights_to_file(char* filename); void load_flights_from_file(char* filename); void save_bookings_to_file(char* filename); void load_bookings_from_file(char* filename); - 辅助函数: void generate_booking_id(char* flight_number, char* booking_id_buf); // 生成订单号 void print_flight_info(Flight* flight); // 打印航班信息 void print_booking_info(Booking* booking); // 打印订票信息 3. 主函数:实现菜单界面。 由于代码较长,下面只给出关键部分的代码框架。 注意:为了简化,我们假设航班号是唯一的,订票时乘客证件号唯一(同一乘客不能重复订同一航班,但不同航班可以)。 下面开始编写部分核心代码:</think># C语言通用链航空订票系统设计与实现 ## 设计思路 基于引用内容[1][2][3],我将设计一个基于通用链的航空订票系统,核心功能包括航班管理、订票和退票。系统使用链存储航班和订票信息,支持数据持久化到文件。 ### 通用链设计 ```c typedef struct ListNode { void* data; // 通用数据指针 struct ListNode* next; // 指向下一个节点 } ListNode; // 创建新节点 ListNode* create_node(void* data) { ListNode* node = (ListNode*)malloc(sizeof(ListNode)); node->data = data; node->next = NULL; return node; } // 插入节点到链尾部 void append_node(ListNode** head, void* data) { ListNode* new_node = create_node(data); if (*head == NULL) { *head = new_node; } else { ListNode* current = *head; while (current->next != NULL) { current = current->next; } current->next = new_node; } } // 从链中删除节点 void delete_node(ListNode** head, void* data, int (*compare)(void*, void*)) { ListNode *current = *head, *prev = NULL; while (current != NULL) { if (compare(current->data, data) == 0) { if (prev == NULL) { *head = current->next; } else { prev->next = current->next; } free(current->data); free(current); return; } prev = current; current = current->next; } } // 查找节点 ListNode* find_node(ListNode* head, void* data, int (*compare)(void*, void*)) { ListNode* current = head; while (current != NULL) { if (compare(current->data, data) == 0) { return current; } current = current->next; } return NULL; } ``` ### 数据结构设计 ```c // 航班信息结构 typedef struct { char flight_number[10]; // 航班号 char destination[50]; // 终点站 char plane_number[10]; // 飞机号 int day_of_week; // 飞行周日 (1-7) char departure_time[6]; // 起飞时间 (HH:MM) float price; // 票价 float discount; // 折扣 int capacity; // 乘员定额 int available_seats; // 余票量 ListNode* bookings; // 已订票乘客链 ListNode* waitlist; // 候补乘客队列 } Flight; // 订票信息结构 typedef struct { char booking_id[20]; // 订单编号 char flight_number[10]; // 航班号 char passenger_name[50]; // 乘客姓名 char id_number[20]; // 证件号 int ticket_count; // 订票数量 } Booking; // 候补乘客结构 typedef struct { char flight_number[10]; // 航班号 char passenger_name[50]; // 乘客姓名 char id_number[20]; // 证件号 int ticket_count; // 需求票数 } WaitPassenger; ``` ## 核心功能实现 ### 航班管理 ```c ListNode* flights_list = NULL; // 全局航班链 // 添加航班 void add_flight() { Flight* flight = (Flight*)malloc(sizeof(Flight)); printf("输入航班号: "); scanf("%s", flight->flight_number); // 其他信息输入... flight->bookings = NULL; flight->waitlist = NULL; append_node(&flights_list, flight); printf("航班添加成功!\n"); } // 查找航班 Flight* find_flight(char* flight_number) { ListNode* node = flights_list; while (node != NULL) { Flight* flight = (Flight*)node->data; if (strcmp(flight->flight_number, flight_number) == 0) { return flight; } node = node->next; } return NULL; } ``` ### 订票系统 ```c ListNode* bookings_list = NULL; // 全局订票链 // 订票函数 void book_ticket() { char flight_number[10]; printf("输入航班号: "); scanf("%s", flight_number); Flight* flight = find_flight(flight_number); if (!flight) { printf("航班不存在!\n"); return; } Booking* booking = (Booking*)malloc(sizeof(Booking)); printf("乘客姓名: "); scanf("%s", booking->passenger_name); printf("证件号: "); scanf("%s", booking->id_number); printf("订票数量: "); scanf("%d", &booking->ticket_count); strcpy(booking->flight_number, flight_number); // 生成唯一订单ID sprintf(booking->booking_id, "%s-%ld", flight_number, time(NULL)); if (flight->available_seats >= booking->ticket_count) { // 有余票,直接订票 flight->available_seats -= booking->ticket_count; append_node(&bookings_list, booking); append_node(&(flight->bookings), booking); printf("订票成功! 订单号: %s\n", booking->booking_id); } else { // 余票不足,加入候补队列 WaitPassenger* wait = (WaitPassenger*)malloc(sizeof(WaitPassenger)); strcpy(wait->flight_number, flight_number); strcpy(wait->passenger_name, booking->passenger_name); strcpy(wait->id_number, booking->id_number); wait->ticket_count = booking->ticket_count; append_node(&(flight->waitlist), wait); printf("当前航班余票不足,已加入候补队列\n"); } } ``` ### 退票系统 ```c // 退票函数 void cancel_ticket() { char booking_id[20]; printf("输入订单号: "); scanf("%s", booking_id); // 在全局订票链中查找订单 ListNode* node = bookings_list; Booking* booking = NULL; while (node != NULL) { Booking* b = (Booking*)node->data; if (strcmp(b->booking_id, booking_id) == 0) { booking = b; break; } node = node->next; } if (!booking) { printf("订单不存在!\n"); return; } Flight* flight = find_flight(booking->flight_number); if (!flight) { printf("关联航班不存在!\n"); return; } // 释放座位 flight->available_seats += booking->ticket_count; // 从航班订票链中删除 delete_node(&(flight->bookings), booking, booking_compare); // 从全局订票链中删除 delete_node(&bookings_list, booking, booking_compare); printf("退票成功! 释放%d个座位\n", booking->ticket_count); // 处理候补队列 process_waitlist(flight); } // 处理候补队列 void process_waitlist(Flight* flight) { if (flight->waitlist == NULL || flight->available_seats <= 0) return; ListNode* node = flight->waitlist; while (node != NULL && flight->available_seats > 0) { WaitPassenger* wait = (WaitPassenger*)node->data; if (wait->ticket_count <= flight->available_seats) { // 满足候补需求 Booking* booking = (Booking*)malloc(sizeof(Booking)); strcpy(booking->flight_number, wait->flight_number); strcpy(booking->passenger_name, wait->passenger_name); strcpy(booking->id_number, wait->id_number); booking->ticket_count = wait->ticket_count; sprintf(booking->booking_id, "%s-%ld", wait->flight_number, time(NULL)); flight->available_seats -= wait->ticket_count; append_node(&bookings_list, booking); append_node(&(flight->bookings), booking); printf("已为候补乘客 %s 订票%d张\n", wait->passenger_name, wait->ticket_count); // 从候补队列中移除 ListNode* to_remove = node; node = node->next; delete_node(&(flight->waitlist), wait, wait_compare); } else { node = node->next; } } } // 比较函数示例 int booking_compare(void* a, void* b) { Booking* ba = (Booking*)a; Booking* bb = (Booking*)b; return strcmp(ba->booking_id, bb->booking_id); } int wait_compare(void* a, void* b) { WaitPassenger* wa = (WaitPassenger*)a; WaitPassenger* wb = (WaitPassenger*)b; return strcmp(wa->id_number, wb->id_number); } ``` ### 文件持久化 ```c // 保存航班数据到文件 void save_flights(const char* filename) { FILE* file = fopen(filename, "wb"); if (!file) return; ListNode* node = flights_list; while (node != NULL) { Flight* flight = (Flight*)node->data; fwrite(flight, sizeof(Flight), 1, file); node = node->next; } fclose(file); } // 从文件加载航班数据 void load_flights(const char* filename) { FILE* file = fopen(filename, "rb"); if (!file) return; Flight flight; while (fread(&flight, sizeof(Flight), 1, file)) { Flight* new_flight = (Flight*)malloc(sizeof(Flight)); memcpy(new_flight, &flight, sizeof(Flight)); new_flight->bookings = NULL; new_flight->waitlist = NULL; append_node(&flights_list, new_flight); } fclose(file); } ``` ## 系统特点 1. **通用链实现**:使用void指针实现通用链结构,支持多种数据类型存储 2. **数据持久化**:航班和订票数据可保存到文件,支持系统重启后恢复 3. **候补队列机制**:当航班满员时,乘客可加入候补队列,退票时自动处理候补 4. **模块化设计**:航班管理、订票、退票功能分离,便于维护和扩展 5. **唯一标识符**:使用航班号+时间戳生成唯一订单号,避免冲突 ## 使用示例 ```c int main() { load_flights("flights.dat"); // 加载航班数据 int choice; do { printf("\n航空订票系统\n"); printf("1. 添加航班\n"); printf("2. 查询航班\n"); printf("3. 订票\n"); printf("4. 退票\n"); printf("5. 退出\n"); printf("选择: "); scanf("%d", &choice); switch(choice) { case 1: add_flight(); break; case 2: search_flights(); break; case 3: book_ticket(); break; case 4: cancel_ticket(); break; case 5: save_flights("flights.dat"); printf("系统退出,数据已保存\n"); break; default: printf("无效选择\n"); } } while(choice != 5); return 0; } ``` ## 扩展建议 1. 增加航班查询功能,按目的地、时间等条件筛选 2. 实现部分退票功能(退部分座位而非全部) 3. 添加用户身份验证系统 4. 实现多线程处理提高并发性能 5. 添加航班状态实时更新功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值