select 查询结果 如: [学号,平均成绩:组函数avg(成绩)]
from 从哪张表中查找数据 如:[涉及到成绩:成绩表score]
where 查询条件 如:[b.课程号='0003' and b.成绩>80] BETWEEN IS NULL NOT IN AND OR
group by 分组 如:[每个学生的平均:按学号分组]
having 对分组结果指定条件 如:[大于60分]
order by 对查询结果排序 如:[增序: 成绩 ASC / 降序: 成绩 DESC];
limit 使用limt子句返回topN(对应这个问题返回的成绩前两名)如:[ limit 2 ==>从0索引开始读取2个]
limit==>从0索引开始 [0,N-1]
组函数: 去重 distinct() 统计总数sum() 计算个数count() 平均数avg() 最大值max() 最小数min()
多表连接:
内连接等值链接,只显示关联数据,自链接 FROM tablea AS A INNER JOIN tableb AS B ON A.key = B.key;
左外连接就是左表参照显示所有,无关联行null LEFT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id;
右连接right join
组合两个查询union(无重复(过滤去重))和union all(有重复[不过滤去重])
视图:虚拟表本身不包含数据,操作和普通表一样,使用实际表一部分,给用户视图权限保证数据安全
存储过程:一系列SQL操作的批处理,代码封装,复用,预先编译性能好
触发器:触发器会在某个表执行以下语句时而自动执行:DELETE、INSERT、UPDATE CREATE TRIGGER 语句创建触发器
查找班级语文英语不及格的人数
SELECT
class as 班级ID,
sum(case when 语文score < 60 then 1 else 0 end) as 不及格人数,
sum(case when 英语score < 60 then 1 else 0 end) as 不及格人数
FROM
class_score
GROUP BY
class;0
查课程1比课程2高学生学号
SELECT t1.sid,t1.score,t2.score
FROM
(select sid,score
from sc
where cid = '01') as t1
JOIN
(select sid,score
from sc
where cid = '02') as t2
ON t1.sid = t2.sid and t1.score>t2.score
查询平均成绩大于60分的同学的学号和平均成绩
SELECT sid,AVG(score) AS AVG
FROM sc
GROUP BY sid
having avg(score)>60
查询所有同学的学号、姓名、选课数、总成绩
SELECT t1.sid,t1.sname,t2.cnt,t2.total_score
FROM
(SELECT sid,sname
FROM student
GROUP BY sid) AS t1
LEFT JOIN
(SELECT sid,COUNT(*) AS cnt,SUM(score) AS total_score
FROM sc
GROUP BY sid) AS t2
ON t1.sid = t2.sid
查询所有课程成绩小于60分的同学的学号、姓名
SELECT DISTINCT s.sid,s.sname
FROM student AS s
JOIN(
SELECT sid
FROM sc
GROUP BY sid
HAVING MAX(score) < 60
)AS t
ON s.sid = t.sid
查询没有学全所有课的同学的学号、姓名;
SELECT s.sid,s.sname
FROM student AS s
LEFT JOIN sc
on s.sid = sc.sid
GROUP BY s.sid
HAVING COUNT(sc.cid)<3
查询学生的总成绩并进行排名
SELECT
sid
,SUM(score) AS total_score
,rank() over (ORDER BY SUM(score) DESC) AS srank
FROM sc
GROUP BY sid
找姓氏包含字符:en的所有员工
SELECT
employee_id,
first_name,
last_name
FROM
employees
WHERE
last_name LIKE '%en%';
触发器是一种特殊的存储过程,就相当于是一个事件的触发装置,它在试图更改触发器所保护的数据时自动执行。
要创建触发器来使班级表中的班内学生数随着学生的添加自动更新,代码如下:
create trigger tri_stu after insert
on student for each row
begin
declare c int;
set c = (select stuCount from class where classID=new.classID);
update class set stuCount = c + 1 where classID = new.classID;
查重名的名字
SELECT * FROM employer WHERE name IN
(SELECT name FROM employer GROUP BY name HAVING COUNT(*) > 1)
like的%:匹配任字符出现任次数,_ 匹配单个字符。jia%匹配开头,可以走索引(%value%走全表),jia_ jia开头且后边只有一个字符,Lucy/_%' escape转义'/以Lucy_开始
select * from user where name like '\[%' escape '\' and name like '%\]' escape '\'
2、魔法元素平衡
public class mofa {
public static long f(long a,long b,long c,long d){
long sum = a + b + c + d;
long avl = sum / 4;
for (long x = avl; x >= 0; x--) {
long left = sum - 4 * x;
long right = 0;
if (x - a > 0) right += x - a;
if (x - b > 0) right += x - b;
if (x - c > 0) right += x - c;
if (x - d > 0) right += x - d;
if (left >= right) {
return 4*x;
}
}
return -1;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
String[] s1 = s.split(" ");
long a = Long.parseLong(s1[0]);
long b = Long.parseLong(s1[1]);
long c = Long.parseLong(s1[2]);
long d = Long.parseLong(s1[3]);
System.out.println(f(a,b,c,d));
}
}
public class mofa {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()){
long[] eles = new long[4];
int sum = 0;
for (int i = 0; i < 4; i++) {
eles[i] = in.nextLong();
sum += eles[i];
}
long avl = sum/4;
long l = 0,r = 0; //l累加比avl小的,r累加比avl大的
for (int i = 0; i < 4; i++) {
long sub = eles[i]-avl;
if(sub<0)
l -= sub; //由于sub小于0,所以用-=
else if(sub>0)
r += sub;
}
long x = 2*l-r; //比较用R去比L,够不够
if (x<=0)
System.out.println(avl*4); //小于等于0说明是够的
else
System.out.println((long)(avl-Math.ceil(((double)x)/4))*4);
//大于0说明不够,那么输出avl-差值除以4向上取整
}
}
}
3、排序
比如:1 3 6 4 5 2
我们观察最大的数6不用移动,
a.6右边的数全部要移动,就是1+1+1=3次(移动的次序不一定,但是次数一定是3)
b.6左边的数,因为排序后和6挨着的一定是4 5,所以前面的两个数不是4 5这样的排序的话一定是移动1+1=2次
c.所以一共需要移动3+2=5次。
综上算法:
1.我们先需要找到最大数所在的序号
2.最大数右边数的个数为a
3.最大数左边的数需要按照自然数的顺序排到N------(N-3, N-2, N-1, N)-----违反规则的个数为b,例如(1 2 5 6 4 3),左边1和2不满足规则的,所以b为2
3.最后的排序的个数为a+b
public class Main1 {
public static void main(String[] args) {
//输入N
Scanner ss1 = new Scanner(System.in);
int N = ss1.nextInt();
//连续输入n个数,并存入数组中
Scanner ss2 = new Scanner(System.in);
String[] str = ss2.nextLine().split(" ");
int[] a = new int[str.length];
for(int i = 0;i<str.length;i++){
a[i] = Integer.parseInt(String.valueOf(str[i]));
}
//计算次数
int pp = fun(N,a);
System.out.println(pp);
}
//函数
private static int fun(int n, int[] arr) {
//1.得到一个有序的数组brr
int[] brr = arr.clone();
Arrays.sort(brr);
int j = n-1; //记录brr的位置
int sum = 0; //记录移动次数
for(int i = n-1;i>=0; i--){
if(arr[i] == brr[j]){
j--;//相等时brr的j向前移动,for循环中i向前移动了,不用管
}else{
sum++;//不等时,次数加1,for循环中i向前移动了,不用管
}
}
return sum;
}
}
4、平行四边形构造
1、首先需要从n条边长里选出平行四边形的四条边(两两相等);
关于输入n与边长均为正数,所以不考虑小于0的情况,但注意边长的值可能会等于0!!
2、再者就已知平行四边形的四条边,需要计算出平行四边形的面积;
打扰了,这里说的是最大的平行四边形面积,所以长方形面积就是最大的平行四边形面积(因为面积等于底乘以高),计算时直接两边相乘。S=x*y。
3、最终选择出的四条边要使得平行四边形的面积最大,就是找到最长的两个相同边长,当然也有可能为一个正方形,即四条边长是一样的。
public class Main2 {
public static void main(String[] args) {
//输入N
Scanner ss1 = new Scanner(System.in);
int N = ss1.nextInt();
//连续输入N个数,存入数组
int[] a=new int[N];
for (int i=0;i<N;i++) {
a[i] = ss1.nextInt();
}
//排序+遍历
System.out.println(fun(a));
}
//排序后找出重复且最大的两个数
private static int fun(int[] arr) {
Arrays.sort(arr);
int i = 0;
int max = 1;//面积
//找出出现过两次且最大的两个数
for (int j = arr.length - 1; j >= 1; j--) {
if (arr[j] == arr[j - 1]) {
max = max * arr[j];
j = j - 1;
i++;
if (i == 2) break;
}
}
if (i < 2) {
return 0;//出现次数为2次的数少于2,不能构成平行四边形
} else {
return max;
}
}
}
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n;
cin>>n;
vector<int> a(n);
for(int i=0;i<n;i++)
{
cin>>a[i];
}
//特殊处理
if(n<4 || n>50000)
cout<<-1;
//根据边长个数与边长大小找最合适的边长
vector<int> count(10,0);
int x=0,y=0;//设置x和y为长方形的边长
float r=0;
for(int i=0;i<n;i++)
{
count[a[i]]++;//统计每个边长出现的次数
if(count[a[i]] >= 2 && count[a[i]]<4 && a[i]>0)// 为长方形时(a[i]>0可以省略,题目已经是输入为正整数)
{
if(a[i] >= x)
{
y = x;
x = a[i];
}
r = x*y;//面积等于长乘以宽
}
else if(count[a[i]] >= 4 && a[i]>0)//为正方形时
{
if(r < a[i]*a[i])
{
r = a[i]*a[i];//面积等于边长相乘
}
}
else//否则不符合题意,直接return 0;
{
cout<<-1;
return 0;
}
}
if(r>0)
cout<<r;
else
cout<<-1;
return 0;
}
5、范围攻击
public static void main(String args[]){
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
int y = cin.nextInt();
int[][] monster = new int[n][2];
for (int i = 0; i < n; i++) {
int x = cin.nextInt();
int hp = cin.nextInt();
monster[i][0] = x;
monster[i][1] = hp;
}
// 注意二维数组的重排序需要实现Comparator接口的对应比较方法
Arrays.sort(monster,Comparator.comparingInt(p -> p[0]));
// 总攻击次数
int time = 0;
// 遍历每一个怪物
for (int i = 0; i < n; i++) {
// 若怪物还有血
while (monster[i][1] > 0) {
// 灭掉该怪物还需多少刀
int killTime = monster[i][1];
// 看看同时还能顺便砍到右边哪些怪
for (int j = i; j < n; j++) {
// 满足该条件,则这些怪也能被顺便砍
if (monster[j][0]-monster[i][0] <= y*2) {
monster[j][1] -= killTime;
}
}
time += killTime;
}
}
System.out.println(time);
}
}
6、股票
public class Main2 {
public static void main(String args[]){
Scanner cin = new Scanner(System.in);
while (cin.hasNext()) {
int m = cin.nextInt();
System.out.println(money(m));
}
}
public static int money(int day) {
// 当前的天数
int now = 1;
// 阶段,现在是连续加1次的阶段,接下来是连续加2次的阶段
int stage = 1;
// 当前余额
int mon = 1;
// 当轮到第day天时,跳出并返回余额
while (now < day) {
// 开始连续加stage次,若没有加完那么多次,说明日期到头了
for(int i=0; i<stage && now<day; i++) {
mon++;
now++;
}
if(now == day) {
return mon;
}
// 加完stage次,以后的stage要加一,即连续多加一次
stage++;
// 然后减一次
mon--;
now++;
}
return mon;
}
}
7、反转数组,片段反转升序排列
import java.util.*;
public class Main3 {
public static void main(String args[]){
Scanner cin = new Scanner(System.in);
int m;
int n;
m = cin.nextInt();
int[] array = new int[m];
// 拷贝数组
int[] copy = new int[m];
for (int i = 0; i < m; i++) {
n = cin.nextInt();
array[i] = n;
copy[i] = n;
}
// 将拷贝数组排序
Arrays.sort(copy);
int left = 0;
int right = m-1;
// 从左找到不相同的位置
while (left < m && copy[left] == array[left]) {
left++;
}
// 当越界,说明整个数组是升序,返回no
if (left >= m ) {
System.out.println("no");
return;
}
// 从右找到不相同的位置
while (right >= 0 && copy[right] == array[right]) {
right--;
}
// 当越界,说明整个数组是升序,返回no
if (right < 0 ) {
System.out.println("no");
return;
}
// 看中间部分的值,array和copy是否反转相等
for (int i = left; i <= right; i++) {
if (array[i] != copy[right-i+left]) {
System.out.println("no");
return;
}
}
System.out.println("yes");
return;
}
}
8、圈地最大面积
public void area(int r){
if(r <= 1) System.out.println(0);
int count = 0;
for(int i = 1;i <= r;i++)
for(int j = 1;j <= r;j++){
double distance = Math.sqrt(i * i + j * j);
if(distance <= r) count++;
}
System.out.println(count * 4);
}
9、序列元素各不相同
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
int[] arr = new int[n];
for(int i = 0;i < n; i++){
arr[i] = cin.nextInt();
}
TreeSet<Integer> set = new TreeSet<>((x,y)->(y-x));
for(int num:arr){
boolean b = set.add(num);
while (!b){
set.remove(num);
num = num*2;
b=set.add(num);
}
}
System.out.print("操作后:");
for (Integer num:set
) {
System.out.print(num+" ");
}
10、种草
public static void main(String[] args) {
PriorityQueue<Integer> priorityQueue = new PriorityQueue();
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();//小草个数
int m = cin.nextInt();//药剂数量
int x = cin.nextInt();//药剂的药效
for (int i = 0; i < n; i++) {
int high = cin.nextInt();
priorityQueue.add(high);
}
while (m-->0){
int low = priorityQueue.peek();
priorityQueue.remove(low);
priorityQueue.add(low+x);
}
System.out.println("药剂用完后的最矮小草的高度为:"+priorityQueue.peek());
}
11、射击游戏
剪花
n只花,第i只的高度为h(i)厘米,最适宜生长的高度是w厘米,所以需要修剪。当修剪一只花时,其右边的花就会长高a厘米。
若每天只能修剪一只花,不超过w不需修剪,费用为1元/厘米,总共需要花费多少钱?
最长因子序列
在x,y之间的正整数,其中a是b的因子,b是c的因子… 最长的序列为多长
射击游戏
sha手狙击枪4发子弹,发射完需要w秒填弹。每秒可以开一枪。敌人每秒出现一次,然后消失。n个敌人,第i个敌人的分数是a[i]。每次剩的最后一个子弹可得双倍分,最多可以得多少分?
12、五个吃货在海边忙活了一天,挖了一堆生蚝
13、求一个数的二进制表示中的1位的个数
14、数组中的跳跃最大长度
15、猴子摘桃
16、把数字翻译成字符串
17、乌鸦喝水
18、棋盘问题
19、白球和黑球
版权声明:本文为qq_38663663原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。